]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-vect-loop.c
2011-03-22 Richard Guenther <rguenther@suse.de>
[thirdparty/gcc.git] / gcc / tree-vect-loop.c
1 /* Loop Vectorization
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Dorit Naishlos <dorit@il.ibm.com> and
5 Ira Rosen <irar@il.ibm.com>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "ggc.h"
28 #include "tree.h"
29 #include "basic-block.h"
30 #include "tree-pretty-print.h"
31 #include "gimple-pretty-print.h"
32 #include "tree-flow.h"
33 #include "tree-dump.h"
34 #include "cfgloop.h"
35 #include "cfglayout.h"
36 #include "expr.h"
37 #include "recog.h"
38 #include "optabs.h"
39 #include "params.h"
40 #include "diagnostic-core.h"
41 #include "tree-chrec.h"
42 #include "tree-scalar-evolution.h"
43 #include "tree-vectorizer.h"
44 #include "target.h"
45
46 /* Loop Vectorization Pass.
47
48 This pass tries to vectorize loops.
49
50 For example, the vectorizer transforms the following simple loop:
51
52 short a[N]; short b[N]; short c[N]; int i;
53
54 for (i=0; i<N; i++){
55 a[i] = b[i] + c[i];
56 }
57
58 as if it was manually vectorized by rewriting the source code into:
59
60 typedef int __attribute__((mode(V8HI))) v8hi;
61 short a[N]; short b[N]; short c[N]; int i;
62 v8hi *pa = (v8hi*)a, *pb = (v8hi*)b, *pc = (v8hi*)c;
63 v8hi va, vb, vc;
64
65 for (i=0; i<N/8; i++){
66 vb = pb[i];
67 vc = pc[i];
68 va = vb + vc;
69 pa[i] = va;
70 }
71
72 The main entry to this pass is vectorize_loops(), in which
73 the vectorizer applies a set of analyses on a given set of loops,
74 followed by the actual vectorization transformation for the loops that
75 had successfully passed the analysis phase.
76 Throughout this pass we make a distinction between two types of
77 data: scalars (which are represented by SSA_NAMES), and memory references
78 ("data-refs"). These two types of data require different handling both
79 during analysis and transformation. The types of data-refs that the
80 vectorizer currently supports are ARRAY_REFS which base is an array DECL
81 (not a pointer), and INDIRECT_REFS through pointers; both array and pointer
82 accesses are required to have a simple (consecutive) access pattern.
83
84 Analysis phase:
85 ===============
86 The driver for the analysis phase is vect_analyze_loop().
87 It applies a set of analyses, some of which rely on the scalar evolution
88 analyzer (scev) developed by Sebastian Pop.
89
90 During the analysis phase the vectorizer records some information
91 per stmt in a "stmt_vec_info" struct which is attached to each stmt in the
92 loop, as well as general information about the loop as a whole, which is
93 recorded in a "loop_vec_info" struct attached to each loop.
94
95 Transformation phase:
96 =====================
97 The loop transformation phase scans all the stmts in the loop, and
98 creates a vector stmt (or a sequence of stmts) for each scalar stmt S in
99 the loop that needs to be vectorized. It inserts the vector code sequence
100 just before the scalar stmt S, and records a pointer to the vector code
101 in STMT_VINFO_VEC_STMT (stmt_info) (stmt_info is the stmt_vec_info struct
102 attached to S). This pointer will be used for the vectorization of following
103 stmts which use the def of stmt S. Stmt S is removed if it writes to memory;
104 otherwise, we rely on dead code elimination for removing it.
105
106 For example, say stmt S1 was vectorized into stmt VS1:
107
108 VS1: vb = px[i];
109 S1: b = x[i]; STMT_VINFO_VEC_STMT (stmt_info (S1)) = VS1
110 S2: a = b;
111
112 To vectorize stmt S2, the vectorizer first finds the stmt that defines
113 the operand 'b' (S1), and gets the relevant vector def 'vb' from the
114 vector stmt VS1 pointed to by STMT_VINFO_VEC_STMT (stmt_info (S1)). The
115 resulting sequence would be:
116
117 VS1: vb = px[i];
118 S1: b = x[i]; STMT_VINFO_VEC_STMT (stmt_info (S1)) = VS1
119 VS2: va = vb;
120 S2: a = b; STMT_VINFO_VEC_STMT (stmt_info (S2)) = VS2
121
122 Operands that are not SSA_NAMEs, are data-refs that appear in
123 load/store operations (like 'x[i]' in S1), and are handled differently.
124
125 Target modeling:
126 =================
127 Currently the only target specific information that is used is the
128 size of the vector (in bytes) - "TARGET_VECTORIZE_UNITS_PER_SIMD_WORD".
129 Targets that can support different sizes of vectors, for now will need
130 to specify one value for "TARGET_VECTORIZE_UNITS_PER_SIMD_WORD". More
131 flexibility will be added in the future.
132
133 Since we only vectorize operations which vector form can be
134 expressed using existing tree codes, to verify that an operation is
135 supported, the vectorizer checks the relevant optab at the relevant
136 machine_mode (e.g, optab_handler (add_optab, V8HImode)). If
137 the value found is CODE_FOR_nothing, then there's no target support, and
138 we can't vectorize the stmt.
139
140 For additional information on this project see:
141 http://gcc.gnu.org/projects/tree-ssa/vectorization.html
142 */
143
144 /* Function vect_determine_vectorization_factor
145
146 Determine the vectorization factor (VF). VF is the number of data elements
147 that are operated upon in parallel in a single iteration of the vectorized
148 loop. For example, when vectorizing a loop that operates on 4byte elements,
149 on a target with vector size (VS) 16byte, the VF is set to 4, since 4
150 elements can fit in a single vector register.
151
152 We currently support vectorization of loops in which all types operated upon
153 are of the same size. Therefore this function currently sets VF according to
154 the size of the types operated upon, and fails if there are multiple sizes
155 in the loop.
156
157 VF is also the factor by which the loop iterations are strip-mined, e.g.:
158 original loop:
159 for (i=0; i<N; i++){
160 a[i] = b[i] + c[i];
161 }
162
163 vectorized loop:
164 for (i=0; i<N; i+=VF){
165 a[i:VF] = b[i:VF] + c[i:VF];
166 }
167 */
168
169 static bool
170 vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
171 {
172 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
173 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
174 int nbbs = loop->num_nodes;
175 gimple_stmt_iterator si;
176 unsigned int vectorization_factor = 0;
177 tree scalar_type;
178 gimple phi;
179 tree vectype;
180 unsigned int nunits;
181 stmt_vec_info stmt_info;
182 int i;
183 HOST_WIDE_INT dummy;
184
185 if (vect_print_dump_info (REPORT_DETAILS))
186 fprintf (vect_dump, "=== vect_determine_vectorization_factor ===");
187
188 for (i = 0; i < nbbs; i++)
189 {
190 basic_block bb = bbs[i];
191
192 for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
193 {
194 phi = gsi_stmt (si);
195 stmt_info = vinfo_for_stmt (phi);
196 if (vect_print_dump_info (REPORT_DETAILS))
197 {
198 fprintf (vect_dump, "==> examining phi: ");
199 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
200 }
201
202 gcc_assert (stmt_info);
203
204 if (STMT_VINFO_RELEVANT_P (stmt_info))
205 {
206 gcc_assert (!STMT_VINFO_VECTYPE (stmt_info));
207 scalar_type = TREE_TYPE (PHI_RESULT (phi));
208
209 if (vect_print_dump_info (REPORT_DETAILS))
210 {
211 fprintf (vect_dump, "get vectype for scalar type: ");
212 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
213 }
214
215 vectype = get_vectype_for_scalar_type (scalar_type);
216 if (!vectype)
217 {
218 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
219 {
220 fprintf (vect_dump,
221 "not vectorized: unsupported data-type ");
222 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
223 }
224 return false;
225 }
226 STMT_VINFO_VECTYPE (stmt_info) = vectype;
227
228 if (vect_print_dump_info (REPORT_DETAILS))
229 {
230 fprintf (vect_dump, "vectype: ");
231 print_generic_expr (vect_dump, vectype, TDF_SLIM);
232 }
233
234 nunits = TYPE_VECTOR_SUBPARTS (vectype);
235 if (vect_print_dump_info (REPORT_DETAILS))
236 fprintf (vect_dump, "nunits = %d", nunits);
237
238 if (!vectorization_factor
239 || (nunits > vectorization_factor))
240 vectorization_factor = nunits;
241 }
242 }
243
244 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
245 {
246 tree vf_vectype;
247 gimple stmt = gsi_stmt (si);
248 stmt_info = vinfo_for_stmt (stmt);
249
250 if (vect_print_dump_info (REPORT_DETAILS))
251 {
252 fprintf (vect_dump, "==> examining statement: ");
253 print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
254 }
255
256 gcc_assert (stmt_info);
257
258 /* skip stmts which do not need to be vectorized. */
259 if (!STMT_VINFO_RELEVANT_P (stmt_info)
260 && !STMT_VINFO_LIVE_P (stmt_info))
261 {
262 if (vect_print_dump_info (REPORT_DETAILS))
263 fprintf (vect_dump, "skip.");
264 continue;
265 }
266
267 if (gimple_get_lhs (stmt) == NULL_TREE)
268 {
269 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
270 {
271 fprintf (vect_dump, "not vectorized: irregular stmt.");
272 print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
273 }
274 return false;
275 }
276
277 if (VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))))
278 {
279 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
280 {
281 fprintf (vect_dump, "not vectorized: vector stmt in loop:");
282 print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
283 }
284 return false;
285 }
286
287 if (STMT_VINFO_VECTYPE (stmt_info))
288 {
289 /* The only case when a vectype had been already set is for stmts
290 that contain a dataref, or for "pattern-stmts" (stmts generated
291 by the vectorizer to represent/replace a certain idiom). */
292 gcc_assert (STMT_VINFO_DATA_REF (stmt_info)
293 || is_pattern_stmt_p (stmt_info));
294 vectype = STMT_VINFO_VECTYPE (stmt_info);
295 }
296 else
297 {
298 gcc_assert (!STMT_VINFO_DATA_REF (stmt_info)
299 && !is_pattern_stmt_p (stmt_info));
300
301 scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
302 if (vect_print_dump_info (REPORT_DETAILS))
303 {
304 fprintf (vect_dump, "get vectype for scalar type: ");
305 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
306 }
307 vectype = get_vectype_for_scalar_type (scalar_type);
308 if (!vectype)
309 {
310 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
311 {
312 fprintf (vect_dump,
313 "not vectorized: unsupported data-type ");
314 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
315 }
316 return false;
317 }
318
319 STMT_VINFO_VECTYPE (stmt_info) = vectype;
320 }
321
322 /* The vectorization factor is according to the smallest
323 scalar type (or the largest vector size, but we only
324 support one vector size per loop). */
325 scalar_type = vect_get_smallest_scalar_type (stmt, &dummy,
326 &dummy);
327 if (vect_print_dump_info (REPORT_DETAILS))
328 {
329 fprintf (vect_dump, "get vectype for scalar type: ");
330 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
331 }
332 vf_vectype = get_vectype_for_scalar_type (scalar_type);
333 if (!vf_vectype)
334 {
335 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
336 {
337 fprintf (vect_dump,
338 "not vectorized: unsupported data-type ");
339 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
340 }
341 return false;
342 }
343
344 if ((GET_MODE_SIZE (TYPE_MODE (vectype))
345 != GET_MODE_SIZE (TYPE_MODE (vf_vectype))))
346 {
347 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
348 {
349 fprintf (vect_dump,
350 "not vectorized: different sized vector "
351 "types in statement, ");
352 print_generic_expr (vect_dump, vectype, TDF_SLIM);
353 fprintf (vect_dump, " and ");
354 print_generic_expr (vect_dump, vf_vectype, TDF_SLIM);
355 }
356 return false;
357 }
358
359 if (vect_print_dump_info (REPORT_DETAILS))
360 {
361 fprintf (vect_dump, "vectype: ");
362 print_generic_expr (vect_dump, vf_vectype, TDF_SLIM);
363 }
364
365 nunits = TYPE_VECTOR_SUBPARTS (vf_vectype);
366 if (vect_print_dump_info (REPORT_DETAILS))
367 fprintf (vect_dump, "nunits = %d", nunits);
368
369 if (!vectorization_factor
370 || (nunits > vectorization_factor))
371 vectorization_factor = nunits;
372 }
373 }
374
375 /* TODO: Analyze cost. Decide if worth while to vectorize. */
376 if (vect_print_dump_info (REPORT_DETAILS))
377 fprintf (vect_dump, "vectorization factor = %d", vectorization_factor);
378 if (vectorization_factor <= 1)
379 {
380 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
381 fprintf (vect_dump, "not vectorized: unsupported data-type");
382 return false;
383 }
384 LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
385
386 return true;
387 }
388
389
390 /* Function vect_is_simple_iv_evolution.
391
392 FORNOW: A simple evolution of an induction variables in the loop is
393 considered a polynomial evolution with constant step. */
394
395 static bool
396 vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
397 tree * step)
398 {
399 tree init_expr;
400 tree step_expr;
401 tree evolution_part = evolution_part_in_loop_num (access_fn, loop_nb);
402
403 /* When there is no evolution in this loop, the evolution function
404 is not "simple". */
405 if (evolution_part == NULL_TREE)
406 return false;
407
408 /* When the evolution is a polynomial of degree >= 2
409 the evolution function is not "simple". */
410 if (tree_is_chrec (evolution_part))
411 return false;
412
413 step_expr = evolution_part;
414 init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, loop_nb));
415
416 if (vect_print_dump_info (REPORT_DETAILS))
417 {
418 fprintf (vect_dump, "step: ");
419 print_generic_expr (vect_dump, step_expr, TDF_SLIM);
420 fprintf (vect_dump, ", init: ");
421 print_generic_expr (vect_dump, init_expr, TDF_SLIM);
422 }
423
424 *init = init_expr;
425 *step = step_expr;
426
427 if (TREE_CODE (step_expr) != INTEGER_CST)
428 {
429 if (vect_print_dump_info (REPORT_DETAILS))
430 fprintf (vect_dump, "step unknown.");
431 return false;
432 }
433
434 return true;
435 }
436
437 /* Function vect_analyze_scalar_cycles_1.
438
439 Examine the cross iteration def-use cycles of scalar variables
440 in LOOP. LOOP_VINFO represents the loop that is now being
441 considered for vectorization (can be LOOP, or an outer-loop
442 enclosing LOOP). */
443
444 static void
445 vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
446 {
447 basic_block bb = loop->header;
448 tree dumy;
449 VEC(gimple,heap) *worklist = VEC_alloc (gimple, heap, 64);
450 gimple_stmt_iterator gsi;
451 bool double_reduc;
452
453 if (vect_print_dump_info (REPORT_DETAILS))
454 fprintf (vect_dump, "=== vect_analyze_scalar_cycles ===");
455
456 /* First - identify all inductions. Reduction detection assumes that all the
457 inductions have been identified, therefore, this order must not be
458 changed. */
459 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
460 {
461 gimple phi = gsi_stmt (gsi);
462 tree access_fn = NULL;
463 tree def = PHI_RESULT (phi);
464 stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi);
465
466 if (vect_print_dump_info (REPORT_DETAILS))
467 {
468 fprintf (vect_dump, "Analyze phi: ");
469 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
470 }
471
472 /* Skip virtual phi's. The data dependences that are associated with
473 virtual defs/uses (i.e., memory accesses) are analyzed elsewhere. */
474 if (!is_gimple_reg (SSA_NAME_VAR (def)))
475 continue;
476
477 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_unknown_def_type;
478
479 /* Analyze the evolution function. */
480 access_fn = analyze_scalar_evolution (loop, def);
481 if (access_fn)
482 STRIP_NOPS (access_fn);
483 if (access_fn && vect_print_dump_info (REPORT_DETAILS))
484 {
485 fprintf (vect_dump, "Access function of PHI: ");
486 print_generic_expr (vect_dump, access_fn, TDF_SLIM);
487 }
488
489 if (!access_fn
490 || !vect_is_simple_iv_evolution (loop->num, access_fn, &dumy, &dumy))
491 {
492 VEC_safe_push (gimple, heap, worklist, phi);
493 continue;
494 }
495
496 if (vect_print_dump_info (REPORT_DETAILS))
497 fprintf (vect_dump, "Detected induction.");
498 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def;
499 }
500
501
502 /* Second - identify all reductions and nested cycles. */
503 while (VEC_length (gimple, worklist) > 0)
504 {
505 gimple phi = VEC_pop (gimple, worklist);
506 tree def = PHI_RESULT (phi);
507 stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi);
508 gimple reduc_stmt;
509 bool nested_cycle;
510
511 if (vect_print_dump_info (REPORT_DETAILS))
512 {
513 fprintf (vect_dump, "Analyze phi: ");
514 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
515 }
516
517 gcc_assert (is_gimple_reg (SSA_NAME_VAR (def)));
518 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_unknown_def_type);
519
520 nested_cycle = (loop != LOOP_VINFO_LOOP (loop_vinfo));
521 reduc_stmt = vect_force_simple_reduction (loop_vinfo, phi, !nested_cycle,
522 &double_reduc);
523 if (reduc_stmt)
524 {
525 if (double_reduc)
526 {
527 if (vect_print_dump_info (REPORT_DETAILS))
528 fprintf (vect_dump, "Detected double reduction.");
529
530 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_double_reduction_def;
531 STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
532 vect_double_reduction_def;
533 }
534 else
535 {
536 if (nested_cycle)
537 {
538 if (vect_print_dump_info (REPORT_DETAILS))
539 fprintf (vect_dump, "Detected vectorizable nested cycle.");
540
541 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_nested_cycle;
542 STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
543 vect_nested_cycle;
544 }
545 else
546 {
547 if (vect_print_dump_info (REPORT_DETAILS))
548 fprintf (vect_dump, "Detected reduction.");
549
550 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_reduction_def;
551 STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
552 vect_reduction_def;
553 /* Store the reduction cycles for possible vectorization in
554 loop-aware SLP. */
555 VEC_safe_push (gimple, heap,
556 LOOP_VINFO_REDUCTIONS (loop_vinfo),
557 reduc_stmt);
558 }
559 }
560 }
561 else
562 if (vect_print_dump_info (REPORT_DETAILS))
563 fprintf (vect_dump, "Unknown def-use cycle pattern.");
564 }
565
566 VEC_free (gimple, heap, worklist);
567 }
568
569
570 /* Function vect_analyze_scalar_cycles.
571
572 Examine the cross iteration def-use cycles of scalar variables, by
573 analyzing the loop-header PHIs of scalar variables. Classify each
574 cycle as one of the following: invariant, induction, reduction, unknown.
575 We do that for the loop represented by LOOP_VINFO, and also to its
576 inner-loop, if exists.
577 Examples for scalar cycles:
578
579 Example1: reduction:
580
581 loop1:
582 for (i=0; i<N; i++)
583 sum += a[i];
584
585 Example2: induction:
586
587 loop2:
588 for (i=0; i<N; i++)
589 a[i] = i; */
590
591 static void
592 vect_analyze_scalar_cycles (loop_vec_info loop_vinfo)
593 {
594 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
595
596 vect_analyze_scalar_cycles_1 (loop_vinfo, loop);
597
598 /* When vectorizing an outer-loop, the inner-loop is executed sequentially.
599 Reductions in such inner-loop therefore have different properties than
600 the reductions in the nest that gets vectorized:
601 1. When vectorized, they are executed in the same order as in the original
602 scalar loop, so we can't change the order of computation when
603 vectorizing them.
604 2. FIXME: Inner-loop reductions can be used in the inner-loop, so the
605 current checks are too strict. */
606
607 if (loop->inner)
608 vect_analyze_scalar_cycles_1 (loop_vinfo, loop->inner);
609 }
610
611 /* Function vect_get_loop_niters.
612
613 Determine how many iterations the loop is executed.
614 If an expression that represents the number of iterations
615 can be constructed, place it in NUMBER_OF_ITERATIONS.
616 Return the loop exit condition. */
617
618 static gimple
619 vect_get_loop_niters (struct loop *loop, tree *number_of_iterations)
620 {
621 tree niters;
622
623 if (vect_print_dump_info (REPORT_DETAILS))
624 fprintf (vect_dump, "=== get_loop_niters ===");
625
626 niters = number_of_exit_cond_executions (loop);
627
628 if (niters != NULL_TREE
629 && niters != chrec_dont_know)
630 {
631 *number_of_iterations = niters;
632
633 if (vect_print_dump_info (REPORT_DETAILS))
634 {
635 fprintf (vect_dump, "==> get_loop_niters:" );
636 print_generic_expr (vect_dump, *number_of_iterations, TDF_SLIM);
637 }
638 }
639
640 return get_loop_exit_condition (loop);
641 }
642
643
644 /* Function bb_in_loop_p
645
646 Used as predicate for dfs order traversal of the loop bbs. */
647
648 static bool
649 bb_in_loop_p (const_basic_block bb, const void *data)
650 {
651 const struct loop *const loop = (const struct loop *)data;
652 if (flow_bb_inside_loop_p (loop, bb))
653 return true;
654 return false;
655 }
656
657
658 /* Function new_loop_vec_info.
659
660 Create and initialize a new loop_vec_info struct for LOOP, as well as
661 stmt_vec_info structs for all the stmts in LOOP. */
662
663 static loop_vec_info
664 new_loop_vec_info (struct loop *loop)
665 {
666 loop_vec_info res;
667 basic_block *bbs;
668 gimple_stmt_iterator si;
669 unsigned int i, nbbs;
670
671 res = (loop_vec_info) xcalloc (1, sizeof (struct _loop_vec_info));
672 LOOP_VINFO_LOOP (res) = loop;
673
674 bbs = get_loop_body (loop);
675
676 /* Create/Update stmt_info for all stmts in the loop. */
677 for (i = 0; i < loop->num_nodes; i++)
678 {
679 basic_block bb = bbs[i];
680
681 /* BBs in a nested inner-loop will have been already processed (because
682 we will have called vect_analyze_loop_form for any nested inner-loop).
683 Therefore, for stmts in an inner-loop we just want to update the
684 STMT_VINFO_LOOP_VINFO field of their stmt_info to point to the new
685 loop_info of the outer-loop we are currently considering to vectorize
686 (instead of the loop_info of the inner-loop).
687 For stmts in other BBs we need to create a stmt_info from scratch. */
688 if (bb->loop_father != loop)
689 {
690 /* Inner-loop bb. */
691 gcc_assert (loop->inner && bb->loop_father == loop->inner);
692 for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
693 {
694 gimple phi = gsi_stmt (si);
695 stmt_vec_info stmt_info = vinfo_for_stmt (phi);
696 loop_vec_info inner_loop_vinfo =
697 STMT_VINFO_LOOP_VINFO (stmt_info);
698 gcc_assert (loop->inner == LOOP_VINFO_LOOP (inner_loop_vinfo));
699 STMT_VINFO_LOOP_VINFO (stmt_info) = res;
700 }
701 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
702 {
703 gimple stmt = gsi_stmt (si);
704 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
705 loop_vec_info inner_loop_vinfo =
706 STMT_VINFO_LOOP_VINFO (stmt_info);
707 gcc_assert (loop->inner == LOOP_VINFO_LOOP (inner_loop_vinfo));
708 STMT_VINFO_LOOP_VINFO (stmt_info) = res;
709 }
710 }
711 else
712 {
713 /* bb in current nest. */
714 for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
715 {
716 gimple phi = gsi_stmt (si);
717 gimple_set_uid (phi, 0);
718 set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, res, NULL));
719 }
720
721 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
722 {
723 gimple stmt = gsi_stmt (si);
724 gimple_set_uid (stmt, 0);
725 set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res, NULL));
726 }
727 }
728 }
729
730 /* CHECKME: We want to visit all BBs before their successors (except for
731 latch blocks, for which this assertion wouldn't hold). In the simple
732 case of the loop forms we allow, a dfs order of the BBs would the same
733 as reversed postorder traversal, so we are safe. */
734
735 free (bbs);
736 bbs = XCNEWVEC (basic_block, loop->num_nodes);
737 nbbs = dfs_enumerate_from (loop->header, 0, bb_in_loop_p,
738 bbs, loop->num_nodes, loop);
739 gcc_assert (nbbs == loop->num_nodes);
740
741 LOOP_VINFO_BBS (res) = bbs;
742 LOOP_VINFO_NITERS (res) = NULL;
743 LOOP_VINFO_NITERS_UNCHANGED (res) = NULL;
744 LOOP_VINFO_COST_MODEL_MIN_ITERS (res) = 0;
745 LOOP_VINFO_VECTORIZABLE_P (res) = 0;
746 LOOP_PEELING_FOR_ALIGNMENT (res) = 0;
747 LOOP_VINFO_VECT_FACTOR (res) = 0;
748 LOOP_VINFO_LOOP_NEST (res) = VEC_alloc (loop_p, heap, 3);
749 LOOP_VINFO_DATAREFS (res) = VEC_alloc (data_reference_p, heap, 10);
750 LOOP_VINFO_DDRS (res) = VEC_alloc (ddr_p, heap, 10 * 10);
751 LOOP_VINFO_UNALIGNED_DR (res) = NULL;
752 LOOP_VINFO_MAY_MISALIGN_STMTS (res) =
753 VEC_alloc (gimple, heap,
754 PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS));
755 LOOP_VINFO_MAY_ALIAS_DDRS (res) =
756 VEC_alloc (ddr_p, heap,
757 PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS));
758 LOOP_VINFO_STRIDED_STORES (res) = VEC_alloc (gimple, heap, 10);
759 LOOP_VINFO_REDUCTIONS (res) = VEC_alloc (gimple, heap, 10);
760 LOOP_VINFO_SLP_INSTANCES (res) = VEC_alloc (slp_instance, heap, 10);
761 LOOP_VINFO_SLP_UNROLLING_FACTOR (res) = 1;
762 LOOP_VINFO_PEELING_HTAB (res) = NULL;
763
764 return res;
765 }
766
767
768 /* Function destroy_loop_vec_info.
769
770 Free LOOP_VINFO struct, as well as all the stmt_vec_info structs of all the
771 stmts in the loop. */
772
773 void
774 destroy_loop_vec_info (loop_vec_info loop_vinfo, bool clean_stmts)
775 {
776 struct loop *loop;
777 basic_block *bbs;
778 int nbbs;
779 gimple_stmt_iterator si;
780 int j;
781 VEC (slp_instance, heap) *slp_instances;
782 slp_instance instance;
783
784 if (!loop_vinfo)
785 return;
786
787 loop = LOOP_VINFO_LOOP (loop_vinfo);
788
789 bbs = LOOP_VINFO_BBS (loop_vinfo);
790 nbbs = loop->num_nodes;
791
792 if (!clean_stmts)
793 {
794 free (LOOP_VINFO_BBS (loop_vinfo));
795 free_data_refs (LOOP_VINFO_DATAREFS (loop_vinfo));
796 free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo));
797 VEC_free (loop_p, heap, LOOP_VINFO_LOOP_NEST (loop_vinfo));
798 VEC_free (gimple, heap, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo));
799 VEC_free (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo));
800
801 free (loop_vinfo);
802 loop->aux = NULL;
803 return;
804 }
805
806 for (j = 0; j < nbbs; j++)
807 {
808 basic_block bb = bbs[j];
809 for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
810 free_stmt_vec_info (gsi_stmt (si));
811
812 for (si = gsi_start_bb (bb); !gsi_end_p (si); )
813 {
814 gimple stmt = gsi_stmt (si);
815 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
816
817 if (stmt_info)
818 {
819 /* Check if this is a "pattern stmt" (introduced by the
820 vectorizer during the pattern recognition pass). */
821 bool remove_stmt_p = false;
822 gimple orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
823 if (orig_stmt)
824 {
825 stmt_vec_info orig_stmt_info = vinfo_for_stmt (orig_stmt);
826 if (orig_stmt_info
827 && STMT_VINFO_IN_PATTERN_P (orig_stmt_info))
828 remove_stmt_p = true;
829 }
830
831 /* Free stmt_vec_info. */
832 free_stmt_vec_info (stmt);
833
834 /* Remove dead "pattern stmts". */
835 if (remove_stmt_p)
836 gsi_remove (&si, true);
837 }
838 gsi_next (&si);
839 }
840 }
841
842 free (LOOP_VINFO_BBS (loop_vinfo));
843 free_data_refs (LOOP_VINFO_DATAREFS (loop_vinfo));
844 free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo));
845 VEC_free (loop_p, heap, LOOP_VINFO_LOOP_NEST (loop_vinfo));
846 VEC_free (gimple, heap, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo));
847 VEC_free (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo));
848 slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
849 FOR_EACH_VEC_ELT (slp_instance, slp_instances, j, instance)
850 vect_free_slp_instance (instance);
851
852 VEC_free (slp_instance, heap, LOOP_VINFO_SLP_INSTANCES (loop_vinfo));
853 VEC_free (gimple, heap, LOOP_VINFO_STRIDED_STORES (loop_vinfo));
854 VEC_free (gimple, heap, LOOP_VINFO_REDUCTIONS (loop_vinfo));
855
856 if (LOOP_VINFO_PEELING_HTAB (loop_vinfo))
857 htab_delete (LOOP_VINFO_PEELING_HTAB (loop_vinfo));
858
859 free (loop_vinfo);
860 loop->aux = NULL;
861 }
862
863
864 /* Function vect_analyze_loop_1.
865
866 Apply a set of analyses on LOOP, and create a loop_vec_info struct
867 for it. The different analyses will record information in the
868 loop_vec_info struct. This is a subset of the analyses applied in
869 vect_analyze_loop, to be applied on an inner-loop nested in the loop
870 that is now considered for (outer-loop) vectorization. */
871
872 static loop_vec_info
873 vect_analyze_loop_1 (struct loop *loop)
874 {
875 loop_vec_info loop_vinfo;
876
877 if (vect_print_dump_info (REPORT_DETAILS))
878 fprintf (vect_dump, "===== analyze_loop_nest_1 =====");
879
880 /* Check the CFG characteristics of the loop (nesting, entry/exit, etc. */
881
882 loop_vinfo = vect_analyze_loop_form (loop);
883 if (!loop_vinfo)
884 {
885 if (vect_print_dump_info (REPORT_DETAILS))
886 fprintf (vect_dump, "bad inner-loop form.");
887 return NULL;
888 }
889
890 return loop_vinfo;
891 }
892
893
894 /* Function vect_analyze_loop_form.
895
896 Verify that certain CFG restrictions hold, including:
897 - the loop has a pre-header
898 - the loop has a single entry and exit
899 - the loop exit condition is simple enough, and the number of iterations
900 can be analyzed (a countable loop). */
901
902 loop_vec_info
903 vect_analyze_loop_form (struct loop *loop)
904 {
905 loop_vec_info loop_vinfo;
906 gimple loop_cond;
907 tree number_of_iterations = NULL;
908 loop_vec_info inner_loop_vinfo = NULL;
909
910 if (vect_print_dump_info (REPORT_DETAILS))
911 fprintf (vect_dump, "=== vect_analyze_loop_form ===");
912
913 /* Different restrictions apply when we are considering an inner-most loop,
914 vs. an outer (nested) loop.
915 (FORNOW. May want to relax some of these restrictions in the future). */
916
917 if (!loop->inner)
918 {
919 /* Inner-most loop. We currently require that the number of BBs is
920 exactly 2 (the header and latch). Vectorizable inner-most loops
921 look like this:
922
923 (pre-header)
924 |
925 header <--------+
926 | | |
927 | +--> latch --+
928 |
929 (exit-bb) */
930
931 if (loop->num_nodes != 2)
932 {
933 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
934 fprintf (vect_dump, "not vectorized: control flow in loop.");
935 return NULL;
936 }
937
938 if (empty_block_p (loop->header))
939 {
940 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
941 fprintf (vect_dump, "not vectorized: empty loop.");
942 return NULL;
943 }
944 }
945 else
946 {
947 struct loop *innerloop = loop->inner;
948 edge entryedge;
949
950 /* Nested loop. We currently require that the loop is doubly-nested,
951 contains a single inner loop, and the number of BBs is exactly 5.
952 Vectorizable outer-loops look like this:
953
954 (pre-header)
955 |
956 header <---+
957 | |
958 inner-loop |
959 | |
960 tail ------+
961 |
962 (exit-bb)
963
964 The inner-loop has the properties expected of inner-most loops
965 as described above. */
966
967 if ((loop->inner)->inner || (loop->inner)->next)
968 {
969 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
970 fprintf (vect_dump, "not vectorized: multiple nested loops.");
971 return NULL;
972 }
973
974 /* Analyze the inner-loop. */
975 inner_loop_vinfo = vect_analyze_loop_1 (loop->inner);
976 if (!inner_loop_vinfo)
977 {
978 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
979 fprintf (vect_dump, "not vectorized: Bad inner loop.");
980 return NULL;
981 }
982
983 if (!expr_invariant_in_loop_p (loop,
984 LOOP_VINFO_NITERS (inner_loop_vinfo)))
985 {
986 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
987 fprintf (vect_dump,
988 "not vectorized: inner-loop count not invariant.");
989 destroy_loop_vec_info (inner_loop_vinfo, true);
990 return NULL;
991 }
992
993 if (loop->num_nodes != 5)
994 {
995 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
996 fprintf (vect_dump, "not vectorized: control flow in loop.");
997 destroy_loop_vec_info (inner_loop_vinfo, true);
998 return NULL;
999 }
1000
1001 gcc_assert (EDGE_COUNT (innerloop->header->preds) == 2);
1002 entryedge = EDGE_PRED (innerloop->header, 0);
1003 if (EDGE_PRED (innerloop->header, 0)->src == innerloop->latch)
1004 entryedge = EDGE_PRED (innerloop->header, 1);
1005
1006 if (entryedge->src != loop->header
1007 || !single_exit (innerloop)
1008 || single_exit (innerloop)->dest != EDGE_PRED (loop->latch, 0)->src)
1009 {
1010 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1011 fprintf (vect_dump, "not vectorized: unsupported outerloop form.");
1012 destroy_loop_vec_info (inner_loop_vinfo, true);
1013 return NULL;
1014 }
1015
1016 if (vect_print_dump_info (REPORT_DETAILS))
1017 fprintf (vect_dump, "Considering outer-loop vectorization.");
1018 }
1019
1020 if (!single_exit (loop)
1021 || EDGE_COUNT (loop->header->preds) != 2)
1022 {
1023 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1024 {
1025 if (!single_exit (loop))
1026 fprintf (vect_dump, "not vectorized: multiple exits.");
1027 else if (EDGE_COUNT (loop->header->preds) != 2)
1028 fprintf (vect_dump, "not vectorized: too many incoming edges.");
1029 }
1030 if (inner_loop_vinfo)
1031 destroy_loop_vec_info (inner_loop_vinfo, true);
1032 return NULL;
1033 }
1034
1035 /* We assume that the loop exit condition is at the end of the loop. i.e,
1036 that the loop is represented as a do-while (with a proper if-guard
1037 before the loop if needed), where the loop header contains all the
1038 executable statements, and the latch is empty. */
1039 if (!empty_block_p (loop->latch)
1040 || !gimple_seq_empty_p (phi_nodes (loop->latch)))
1041 {
1042 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1043 fprintf (vect_dump, "not vectorized: unexpected loop form.");
1044 if (inner_loop_vinfo)
1045 destroy_loop_vec_info (inner_loop_vinfo, true);
1046 return NULL;
1047 }
1048
1049 /* Make sure there exists a single-predecessor exit bb: */
1050 if (!single_pred_p (single_exit (loop)->dest))
1051 {
1052 edge e = single_exit (loop);
1053 if (!(e->flags & EDGE_ABNORMAL))
1054 {
1055 split_loop_exit_edge (e);
1056 if (vect_print_dump_info (REPORT_DETAILS))
1057 fprintf (vect_dump, "split exit edge.");
1058 }
1059 else
1060 {
1061 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1062 fprintf (vect_dump, "not vectorized: abnormal loop exit edge.");
1063 if (inner_loop_vinfo)
1064 destroy_loop_vec_info (inner_loop_vinfo, true);
1065 return NULL;
1066 }
1067 }
1068
1069 loop_cond = vect_get_loop_niters (loop, &number_of_iterations);
1070 if (!loop_cond)
1071 {
1072 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1073 fprintf (vect_dump, "not vectorized: complicated exit condition.");
1074 if (inner_loop_vinfo)
1075 destroy_loop_vec_info (inner_loop_vinfo, true);
1076 return NULL;
1077 }
1078
1079 if (!number_of_iterations)
1080 {
1081 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1082 fprintf (vect_dump,
1083 "not vectorized: number of iterations cannot be computed.");
1084 if (inner_loop_vinfo)
1085 destroy_loop_vec_info (inner_loop_vinfo, true);
1086 return NULL;
1087 }
1088
1089 if (chrec_contains_undetermined (number_of_iterations))
1090 {
1091 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
1092 fprintf (vect_dump, "Infinite number of iterations.");
1093 if (inner_loop_vinfo)
1094 destroy_loop_vec_info (inner_loop_vinfo, true);
1095 return NULL;
1096 }
1097
1098 if (!NITERS_KNOWN_P (number_of_iterations))
1099 {
1100 if (vect_print_dump_info (REPORT_DETAILS))
1101 {
1102 fprintf (vect_dump, "Symbolic number of iterations is ");
1103 print_generic_expr (vect_dump, number_of_iterations, TDF_DETAILS);
1104 }
1105 }
1106 else if (TREE_INT_CST_LOW (number_of_iterations) == 0)
1107 {
1108 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1109 fprintf (vect_dump, "not vectorized: number of iterations = 0.");
1110 if (inner_loop_vinfo)
1111 destroy_loop_vec_info (inner_loop_vinfo, false);
1112 return NULL;
1113 }
1114
1115 loop_vinfo = new_loop_vec_info (loop);
1116 LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
1117 LOOP_VINFO_NITERS_UNCHANGED (loop_vinfo) = number_of_iterations;
1118
1119 STMT_VINFO_TYPE (vinfo_for_stmt (loop_cond)) = loop_exit_ctrl_vec_info_type;
1120
1121 /* CHECKME: May want to keep it around it in the future. */
1122 if (inner_loop_vinfo)
1123 destroy_loop_vec_info (inner_loop_vinfo, false);
1124
1125 gcc_assert (!loop->aux);
1126 loop->aux = loop_vinfo;
1127 return loop_vinfo;
1128 }
1129
1130
1131 /* Get cost by calling cost target builtin. */
1132
1133 static inline int
1134 vect_get_cost (enum vect_cost_for_stmt type_of_cost)
1135 {
1136 tree dummy_type = NULL;
1137 int dummy = 0;
1138
1139 return targetm.vectorize.builtin_vectorization_cost (type_of_cost,
1140 dummy_type, dummy);
1141 }
1142
1143
1144 /* Function vect_analyze_loop_operations.
1145
1146 Scan the loop stmts and make sure they are all vectorizable. */
1147
1148 static bool
1149 vect_analyze_loop_operations (loop_vec_info loop_vinfo)
1150 {
1151 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1152 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
1153 int nbbs = loop->num_nodes;
1154 gimple_stmt_iterator si;
1155 unsigned int vectorization_factor = 0;
1156 int i;
1157 gimple phi;
1158 stmt_vec_info stmt_info;
1159 bool need_to_vectorize = false;
1160 int min_profitable_iters;
1161 int min_scalar_loop_bound;
1162 unsigned int th;
1163 bool only_slp_in_loop = true, ok;
1164
1165 if (vect_print_dump_info (REPORT_DETAILS))
1166 fprintf (vect_dump, "=== vect_analyze_loop_operations ===");
1167
1168 gcc_assert (LOOP_VINFO_VECT_FACTOR (loop_vinfo));
1169 vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
1170
1171 for (i = 0; i < nbbs; i++)
1172 {
1173 basic_block bb = bbs[i];
1174
1175 for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
1176 {
1177 phi = gsi_stmt (si);
1178 ok = true;
1179
1180 stmt_info = vinfo_for_stmt (phi);
1181 if (vect_print_dump_info (REPORT_DETAILS))
1182 {
1183 fprintf (vect_dump, "examining phi: ");
1184 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
1185 }
1186
1187 if (! is_loop_header_bb_p (bb))
1188 {
1189 /* inner-loop loop-closed exit phi in outer-loop vectorization
1190 (i.e. a phi in the tail of the outer-loop).
1191 FORNOW: we currently don't support the case that these phis
1192 are not used in the outerloop (unless it is double reduction,
1193 i.e., this phi is vect_reduction_def), cause this case
1194 requires to actually do something here. */
1195 if ((!STMT_VINFO_RELEVANT_P (stmt_info)
1196 || STMT_VINFO_LIVE_P (stmt_info))
1197 && STMT_VINFO_DEF_TYPE (stmt_info)
1198 != vect_double_reduction_def)
1199 {
1200 if (vect_print_dump_info (REPORT_DETAILS))
1201 fprintf (vect_dump,
1202 "Unsupported loop-closed phi in outer-loop.");
1203 return false;
1204 }
1205 continue;
1206 }
1207
1208 gcc_assert (stmt_info);
1209
1210 if (STMT_VINFO_LIVE_P (stmt_info))
1211 {
1212 /* FORNOW: not yet supported. */
1213 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1214 fprintf (vect_dump, "not vectorized: value used after loop.");
1215 return false;
1216 }
1217
1218 if (STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_scope
1219 && STMT_VINFO_DEF_TYPE (stmt_info) != vect_induction_def)
1220 {
1221 /* A scalar-dependence cycle that we don't support. */
1222 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1223 fprintf (vect_dump, "not vectorized: scalar dependence cycle.");
1224 return false;
1225 }
1226
1227 if (STMT_VINFO_RELEVANT_P (stmt_info))
1228 {
1229 need_to_vectorize = true;
1230 if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def)
1231 ok = vectorizable_induction (phi, NULL, NULL);
1232 }
1233
1234 if (!ok)
1235 {
1236 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1237 {
1238 fprintf (vect_dump,
1239 "not vectorized: relevant phi not supported: ");
1240 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
1241 }
1242 return false;
1243 }
1244 }
1245
1246 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
1247 {
1248 gimple stmt = gsi_stmt (si);
1249 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1250
1251 gcc_assert (stmt_info);
1252
1253 if (!vect_analyze_stmt (stmt, &need_to_vectorize, NULL))
1254 return false;
1255
1256 if ((STMT_VINFO_RELEVANT_P (stmt_info)
1257 || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
1258 && !PURE_SLP_STMT (stmt_info))
1259 /* STMT needs both SLP and loop-based vectorization. */
1260 only_slp_in_loop = false;
1261 }
1262 } /* bbs */
1263
1264 /* All operations in the loop are either irrelevant (deal with loop
1265 control, or dead), or only used outside the loop and can be moved
1266 out of the loop (e.g. invariants, inductions). The loop can be
1267 optimized away by scalar optimizations. We're better off not
1268 touching this loop. */
1269 if (!need_to_vectorize)
1270 {
1271 if (vect_print_dump_info (REPORT_DETAILS))
1272 fprintf (vect_dump,
1273 "All the computation can be taken out of the loop.");
1274 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1275 fprintf (vect_dump,
1276 "not vectorized: redundant loop. no profit to vectorize.");
1277 return false;
1278 }
1279
1280 /* If all the stmts in the loop can be SLPed, we perform only SLP, and
1281 vectorization factor of the loop is the unrolling factor required by the
1282 SLP instances. If that unrolling factor is 1, we say, that we perform
1283 pure SLP on loop - cross iteration parallelism is not exploited. */
1284 if (only_slp_in_loop)
1285 vectorization_factor = LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo);
1286 else
1287 vectorization_factor = least_common_multiple (vectorization_factor,
1288 LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo));
1289
1290 LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
1291
1292 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
1293 && vect_print_dump_info (REPORT_DETAILS))
1294 fprintf (vect_dump,
1295 "vectorization_factor = %d, niters = " HOST_WIDE_INT_PRINT_DEC,
1296 vectorization_factor, LOOP_VINFO_INT_NITERS (loop_vinfo));
1297
1298 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
1299 && (LOOP_VINFO_INT_NITERS (loop_vinfo) < vectorization_factor))
1300 {
1301 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1302 fprintf (vect_dump, "not vectorized: iteration count too small.");
1303 if (vect_print_dump_info (REPORT_DETAILS))
1304 fprintf (vect_dump,"not vectorized: iteration count smaller than "
1305 "vectorization factor.");
1306 return false;
1307 }
1308
1309 /* Analyze cost. Decide if worth while to vectorize. */
1310
1311 /* Once VF is set, SLP costs should be updated since the number of created
1312 vector stmts depends on VF. */
1313 vect_update_slp_costs_according_to_vf (loop_vinfo);
1314
1315 min_profitable_iters = vect_estimate_min_profitable_iters (loop_vinfo);
1316 LOOP_VINFO_COST_MODEL_MIN_ITERS (loop_vinfo) = min_profitable_iters;
1317
1318 if (min_profitable_iters < 0)
1319 {
1320 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1321 fprintf (vect_dump, "not vectorized: vectorization not profitable.");
1322 if (vect_print_dump_info (REPORT_DETAILS))
1323 fprintf (vect_dump, "not vectorized: vector version will never be "
1324 "profitable.");
1325 return false;
1326 }
1327
1328 min_scalar_loop_bound = ((PARAM_VALUE (PARAM_MIN_VECT_LOOP_BOUND)
1329 * vectorization_factor) - 1);
1330
1331 /* Use the cost model only if it is more conservative than user specified
1332 threshold. */
1333
1334 th = (unsigned) min_scalar_loop_bound;
1335 if (min_profitable_iters
1336 && (!min_scalar_loop_bound
1337 || min_profitable_iters > min_scalar_loop_bound))
1338 th = (unsigned) min_profitable_iters;
1339
1340 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
1341 && LOOP_VINFO_INT_NITERS (loop_vinfo) <= th)
1342 {
1343 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1344 fprintf (vect_dump, "not vectorized: vectorization not "
1345 "profitable.");
1346 if (vect_print_dump_info (REPORT_DETAILS))
1347 fprintf (vect_dump, "not vectorized: iteration count smaller than "
1348 "user specified loop bound parameter or minimum "
1349 "profitable iterations (whichever is more conservative).");
1350 return false;
1351 }
1352
1353 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
1354 || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0
1355 || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
1356 {
1357 if (vect_print_dump_info (REPORT_DETAILS))
1358 fprintf (vect_dump, "epilog loop required.");
1359 if (!vect_can_advance_ivs_p (loop_vinfo))
1360 {
1361 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1362 fprintf (vect_dump,
1363 "not vectorized: can't create epilog loop 1.");
1364 return false;
1365 }
1366 if (!slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
1367 {
1368 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1369 fprintf (vect_dump,
1370 "not vectorized: can't create epilog loop 2.");
1371 return false;
1372 }
1373 }
1374
1375 return true;
1376 }
1377
1378
1379 /* Function vect_analyze_loop_2.
1380
1381 Apply a set of analyses on LOOP, and create a loop_vec_info struct
1382 for it. The different analyses will record information in the
1383 loop_vec_info struct. */
1384 static bool
1385 vect_analyze_loop_2 (loop_vec_info loop_vinfo)
1386 {
1387 bool ok, dummy;
1388 int max_vf = MAX_VECTORIZATION_FACTOR;
1389 int min_vf = 2;
1390
1391 /* Find all data references in the loop (which correspond to vdefs/vuses)
1392 and analyze their evolution in the loop. Also adjust the minimal
1393 vectorization factor according to the loads and stores.
1394
1395 FORNOW: Handle only simple, array references, which
1396 alignment can be forced, and aligned pointer-references. */
1397
1398 ok = vect_analyze_data_refs (loop_vinfo, NULL, &min_vf);
1399 if (!ok)
1400 {
1401 if (vect_print_dump_info (REPORT_DETAILS))
1402 fprintf (vect_dump, "bad data references.");
1403 return false;
1404 }
1405
1406 /* Classify all cross-iteration scalar data-flow cycles.
1407 Cross-iteration cycles caused by virtual phis are analyzed separately. */
1408
1409 vect_analyze_scalar_cycles (loop_vinfo);
1410
1411 vect_pattern_recog (loop_vinfo);
1412
1413 /* Data-flow analysis to detect stmts that do not need to be vectorized. */
1414
1415 ok = vect_mark_stmts_to_be_vectorized (loop_vinfo);
1416 if (!ok)
1417 {
1418 if (vect_print_dump_info (REPORT_DETAILS))
1419 fprintf (vect_dump, "unexpected pattern.");
1420 return false;
1421 }
1422
1423 /* Analyze data dependences between the data-refs in the loop
1424 and adjust the maximum vectorization factor according to
1425 the dependences.
1426 FORNOW: fail at the first data dependence that we encounter. */
1427
1428 ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf, &dummy);
1429 if (!ok
1430 || max_vf < min_vf)
1431 {
1432 if (vect_print_dump_info (REPORT_DETAILS))
1433 fprintf (vect_dump, "bad data dependence.");
1434 return false;
1435 }
1436
1437 ok = vect_determine_vectorization_factor (loop_vinfo);
1438 if (!ok)
1439 {
1440 if (vect_print_dump_info (REPORT_DETAILS))
1441 fprintf (vect_dump, "can't determine vectorization factor.");
1442 return false;
1443 }
1444 if (max_vf < LOOP_VINFO_VECT_FACTOR (loop_vinfo))
1445 {
1446 if (vect_print_dump_info (REPORT_DETAILS))
1447 fprintf (vect_dump, "bad data dependence.");
1448 return false;
1449 }
1450
1451 /* Analyze the alignment of the data-refs in the loop.
1452 Fail if a data reference is found that cannot be vectorized. */
1453
1454 ok = vect_analyze_data_refs_alignment (loop_vinfo, NULL);
1455 if (!ok)
1456 {
1457 if (vect_print_dump_info (REPORT_DETAILS))
1458 fprintf (vect_dump, "bad data alignment.");
1459 return false;
1460 }
1461
1462 /* Analyze the access patterns of the data-refs in the loop (consecutive,
1463 complex, etc.). FORNOW: Only handle consecutive access pattern. */
1464
1465 ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
1466 if (!ok)
1467 {
1468 if (vect_print_dump_info (REPORT_DETAILS))
1469 fprintf (vect_dump, "bad data access.");
1470 return false;
1471 }
1472
1473 /* Prune the list of ddrs to be tested at run-time by versioning for alias.
1474 It is important to call pruning after vect_analyze_data_ref_accesses,
1475 since we use grouping information gathered by interleaving analysis. */
1476 ok = vect_prune_runtime_alias_test_list (loop_vinfo);
1477 if (!ok)
1478 {
1479 if (vect_print_dump_info (REPORT_DETAILS))
1480 fprintf (vect_dump, "too long list of versioning for alias "
1481 "run-time tests.");
1482 return false;
1483 }
1484
1485 /* This pass will decide on using loop versioning and/or loop peeling in
1486 order to enhance the alignment of data references in the loop. */
1487
1488 ok = vect_enhance_data_refs_alignment (loop_vinfo);
1489 if (!ok)
1490 {
1491 if (vect_print_dump_info (REPORT_DETAILS))
1492 fprintf (vect_dump, "bad data alignment.");
1493 return false;
1494 }
1495
1496 /* Check the SLP opportunities in the loop, analyze and build SLP trees. */
1497 ok = vect_analyze_slp (loop_vinfo, NULL);
1498 if (ok)
1499 {
1500 /* Decide which possible SLP instances to SLP. */
1501 vect_make_slp_decision (loop_vinfo);
1502
1503 /* Find stmts that need to be both vectorized and SLPed. */
1504 vect_detect_hybrid_slp (loop_vinfo);
1505 }
1506
1507 /* Scan all the operations in the loop and make sure they are
1508 vectorizable. */
1509
1510 ok = vect_analyze_loop_operations (loop_vinfo);
1511 if (!ok)
1512 {
1513 if (vect_print_dump_info (REPORT_DETAILS))
1514 fprintf (vect_dump, "bad operation or unsupported loop bound.");
1515 return false;
1516 }
1517
1518 return true;
1519 }
1520
1521 /* Function vect_analyze_loop.
1522
1523 Apply a set of analyses on LOOP, and create a loop_vec_info struct
1524 for it. The different analyses will record information in the
1525 loop_vec_info struct. */
1526 loop_vec_info
1527 vect_analyze_loop (struct loop *loop)
1528 {
1529 loop_vec_info loop_vinfo;
1530 unsigned int vector_sizes;
1531
1532 /* Autodetect first vector size we try. */
1533 current_vector_size = 0;
1534 vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
1535
1536 if (vect_print_dump_info (REPORT_DETAILS))
1537 fprintf (vect_dump, "===== analyze_loop_nest =====");
1538
1539 if (loop_outer (loop)
1540 && loop_vec_info_for_loop (loop_outer (loop))
1541 && LOOP_VINFO_VECTORIZABLE_P (loop_vec_info_for_loop (loop_outer (loop))))
1542 {
1543 if (vect_print_dump_info (REPORT_DETAILS))
1544 fprintf (vect_dump, "outer-loop already vectorized.");
1545 return NULL;
1546 }
1547
1548 while (1)
1549 {
1550 /* Check the CFG characteristics of the loop (nesting, entry/exit). */
1551 loop_vinfo = vect_analyze_loop_form (loop);
1552 if (!loop_vinfo)
1553 {
1554 if (vect_print_dump_info (REPORT_DETAILS))
1555 fprintf (vect_dump, "bad loop form.");
1556 return NULL;
1557 }
1558
1559 if (vect_analyze_loop_2 (loop_vinfo))
1560 {
1561 LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
1562
1563 return loop_vinfo;
1564 }
1565
1566 destroy_loop_vec_info (loop_vinfo, true);
1567
1568 vector_sizes &= ~current_vector_size;
1569 if (vector_sizes == 0
1570 || current_vector_size == 0)
1571 return NULL;
1572
1573 /* Try the next biggest vector size. */
1574 current_vector_size = 1 << floor_log2 (vector_sizes);
1575 if (vect_print_dump_info (REPORT_DETAILS))
1576 fprintf (vect_dump, "***** Re-trying analysis with "
1577 "vector size %d\n", current_vector_size);
1578 }
1579 }
1580
1581
1582 /* Function reduction_code_for_scalar_code
1583
1584 Input:
1585 CODE - tree_code of a reduction operations.
1586
1587 Output:
1588 REDUC_CODE - the corresponding tree-code to be used to reduce the
1589 vector of partial results into a single scalar result (which
1590 will also reside in a vector) or ERROR_MARK if the operation is
1591 a supported reduction operation, but does not have such tree-code.
1592
1593 Return FALSE if CODE currently cannot be vectorized as reduction. */
1594
1595 static bool
1596 reduction_code_for_scalar_code (enum tree_code code,
1597 enum tree_code *reduc_code)
1598 {
1599 switch (code)
1600 {
1601 case MAX_EXPR:
1602 *reduc_code = REDUC_MAX_EXPR;
1603 return true;
1604
1605 case MIN_EXPR:
1606 *reduc_code = REDUC_MIN_EXPR;
1607 return true;
1608
1609 case PLUS_EXPR:
1610 *reduc_code = REDUC_PLUS_EXPR;
1611 return true;
1612
1613 case MULT_EXPR:
1614 case MINUS_EXPR:
1615 case BIT_IOR_EXPR:
1616 case BIT_XOR_EXPR:
1617 case BIT_AND_EXPR:
1618 *reduc_code = ERROR_MARK;
1619 return true;
1620
1621 default:
1622 return false;
1623 }
1624 }
1625
1626
1627 /* Error reporting helper for vect_is_simple_reduction below. GIMPLE statement
1628 STMT is printed with a message MSG. */
1629
1630 static void
1631 report_vect_op (gimple stmt, const char *msg)
1632 {
1633 fprintf (vect_dump, "%s", msg);
1634 print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
1635 }
1636
1637
1638 /* Function vect_is_simple_reduction_1
1639
1640 (1) Detect a cross-iteration def-use cycle that represents a simple
1641 reduction computation. We look for the following pattern:
1642
1643 loop_header:
1644 a1 = phi < a0, a2 >
1645 a3 = ...
1646 a2 = operation (a3, a1)
1647
1648 such that:
1649 1. operation is commutative and associative and it is safe to
1650 change the order of the computation (if CHECK_REDUCTION is true)
1651 2. no uses for a2 in the loop (a2 is used out of the loop)
1652 3. no uses of a1 in the loop besides the reduction operation
1653 4. no uses of a1 outside the loop.
1654
1655 Conditions 1,4 are tested here.
1656 Conditions 2,3 are tested in vect_mark_stmts_to_be_vectorized.
1657
1658 (2) Detect a cross-iteration def-use cycle in nested loops, i.e.,
1659 nested cycles, if CHECK_REDUCTION is false.
1660
1661 (3) Detect cycles of phi nodes in outer-loop vectorization, i.e., double
1662 reductions:
1663
1664 a1 = phi < a0, a2 >
1665 inner loop (def of a3)
1666 a2 = phi < a3 >
1667
1668 If MODIFY is true it tries also to rework the code in-place to enable
1669 detection of more reduction patterns. For the time being we rewrite
1670 "res -= RHS" into "rhs += -RHS" when it seems worthwhile.
1671 */
1672
1673 static gimple
1674 vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
1675 bool check_reduction, bool *double_reduc,
1676 bool modify)
1677 {
1678 struct loop *loop = (gimple_bb (phi))->loop_father;
1679 struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
1680 edge latch_e = loop_latch_edge (loop);
1681 tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
1682 gimple def_stmt, def1 = NULL, def2 = NULL;
1683 enum tree_code orig_code, code;
1684 tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE;
1685 tree type;
1686 int nloop_uses;
1687 tree name;
1688 imm_use_iterator imm_iter;
1689 use_operand_p use_p;
1690 bool phi_def;
1691
1692 *double_reduc = false;
1693
1694 /* If CHECK_REDUCTION is true, we assume inner-most loop vectorization,
1695 otherwise, we assume outer loop vectorization. */
1696 gcc_assert ((check_reduction && loop == vect_loop)
1697 || (!check_reduction && flow_loop_nested_p (vect_loop, loop)));
1698
1699 name = PHI_RESULT (phi);
1700 nloop_uses = 0;
1701 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
1702 {
1703 gimple use_stmt = USE_STMT (use_p);
1704 if (is_gimple_debug (use_stmt))
1705 continue;
1706
1707 if (!flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
1708 {
1709 if (vect_print_dump_info (REPORT_DETAILS))
1710 fprintf (vect_dump, "intermediate value used outside loop.");
1711
1712 return NULL;
1713 }
1714
1715 if (vinfo_for_stmt (use_stmt)
1716 && !is_pattern_stmt_p (vinfo_for_stmt (use_stmt)))
1717 nloop_uses++;
1718 if (nloop_uses > 1)
1719 {
1720 if (vect_print_dump_info (REPORT_DETAILS))
1721 fprintf (vect_dump, "reduction used in loop.");
1722 return NULL;
1723 }
1724 }
1725
1726 if (TREE_CODE (loop_arg) != SSA_NAME)
1727 {
1728 if (vect_print_dump_info (REPORT_DETAILS))
1729 {
1730 fprintf (vect_dump, "reduction: not ssa_name: ");
1731 print_generic_expr (vect_dump, loop_arg, TDF_SLIM);
1732 }
1733 return NULL;
1734 }
1735
1736 def_stmt = SSA_NAME_DEF_STMT (loop_arg);
1737 if (!def_stmt)
1738 {
1739 if (vect_print_dump_info (REPORT_DETAILS))
1740 fprintf (vect_dump, "reduction: no def_stmt.");
1741 return NULL;
1742 }
1743
1744 if (!is_gimple_assign (def_stmt) && gimple_code (def_stmt) != GIMPLE_PHI)
1745 {
1746 if (vect_print_dump_info (REPORT_DETAILS))
1747 print_gimple_stmt (vect_dump, def_stmt, 0, TDF_SLIM);
1748 return NULL;
1749 }
1750
1751 if (is_gimple_assign (def_stmt))
1752 {
1753 name = gimple_assign_lhs (def_stmt);
1754 phi_def = false;
1755 }
1756 else
1757 {
1758 name = PHI_RESULT (def_stmt);
1759 phi_def = true;
1760 }
1761
1762 nloop_uses = 0;
1763 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
1764 {
1765 gimple use_stmt = USE_STMT (use_p);
1766 if (is_gimple_debug (use_stmt))
1767 continue;
1768 if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt))
1769 && vinfo_for_stmt (use_stmt)
1770 && !is_pattern_stmt_p (vinfo_for_stmt (use_stmt)))
1771 nloop_uses++;
1772 if (nloop_uses > 1)
1773 {
1774 if (vect_print_dump_info (REPORT_DETAILS))
1775 fprintf (vect_dump, "reduction used in loop.");
1776 return NULL;
1777 }
1778 }
1779
1780 /* If DEF_STMT is a phi node itself, we expect it to have a single argument
1781 defined in the inner loop. */
1782 if (phi_def)
1783 {
1784 op1 = PHI_ARG_DEF (def_stmt, 0);
1785
1786 if (gimple_phi_num_args (def_stmt) != 1
1787 || TREE_CODE (op1) != SSA_NAME)
1788 {
1789 if (vect_print_dump_info (REPORT_DETAILS))
1790 fprintf (vect_dump, "unsupported phi node definition.");
1791
1792 return NULL;
1793 }
1794
1795 def1 = SSA_NAME_DEF_STMT (op1);
1796 if (flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
1797 && loop->inner
1798 && flow_bb_inside_loop_p (loop->inner, gimple_bb (def1))
1799 && is_gimple_assign (def1))
1800 {
1801 if (vect_print_dump_info (REPORT_DETAILS))
1802 report_vect_op (def_stmt, "detected double reduction: ");
1803
1804 *double_reduc = true;
1805 return def_stmt;
1806 }
1807
1808 return NULL;
1809 }
1810
1811 code = orig_code = gimple_assign_rhs_code (def_stmt);
1812
1813 /* We can handle "res -= x[i]", which is non-associative by
1814 simply rewriting this into "res += -x[i]". Avoid changing
1815 gimple instruction for the first simple tests and only do this
1816 if we're allowed to change code at all. */
1817 if (code == MINUS_EXPR
1818 && modify
1819 && (op1 = gimple_assign_rhs1 (def_stmt))
1820 && TREE_CODE (op1) == SSA_NAME
1821 && SSA_NAME_DEF_STMT (op1) == phi)
1822 code = PLUS_EXPR;
1823
1824 if (check_reduction
1825 && (!commutative_tree_code (code) || !associative_tree_code (code)))
1826 {
1827 if (vect_print_dump_info (REPORT_DETAILS))
1828 report_vect_op (def_stmt, "reduction: not commutative/associative: ");
1829 return NULL;
1830 }
1831
1832 if (get_gimple_rhs_class (code) != GIMPLE_BINARY_RHS)
1833 {
1834 if (code != COND_EXPR)
1835 {
1836 if (vect_print_dump_info (REPORT_DETAILS))
1837 report_vect_op (def_stmt, "reduction: not binary operation: ");
1838
1839 return NULL;
1840 }
1841
1842 op3 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
1843 if (COMPARISON_CLASS_P (op3))
1844 {
1845 op4 = TREE_OPERAND (op3, 1);
1846 op3 = TREE_OPERAND (op3, 0);
1847 }
1848
1849 op1 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 1);
1850 op2 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 2);
1851
1852 if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
1853 {
1854 if (vect_print_dump_info (REPORT_DETAILS))
1855 report_vect_op (def_stmt, "reduction: uses not ssa_names: ");
1856
1857 return NULL;
1858 }
1859 }
1860 else
1861 {
1862 op1 = gimple_assign_rhs1 (def_stmt);
1863 op2 = gimple_assign_rhs2 (def_stmt);
1864
1865 if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
1866 {
1867 if (vect_print_dump_info (REPORT_DETAILS))
1868 report_vect_op (def_stmt, "reduction: uses not ssa_names: ");
1869
1870 return NULL;
1871 }
1872 }
1873
1874 type = TREE_TYPE (gimple_assign_lhs (def_stmt));
1875 if ((TREE_CODE (op1) == SSA_NAME
1876 && !types_compatible_p (type,TREE_TYPE (op1)))
1877 || (TREE_CODE (op2) == SSA_NAME
1878 && !types_compatible_p (type, TREE_TYPE (op2)))
1879 || (op3 && TREE_CODE (op3) == SSA_NAME
1880 && !types_compatible_p (type, TREE_TYPE (op3)))
1881 || (op4 && TREE_CODE (op4) == SSA_NAME
1882 && !types_compatible_p (type, TREE_TYPE (op4))))
1883 {
1884 if (vect_print_dump_info (REPORT_DETAILS))
1885 {
1886 fprintf (vect_dump, "reduction: multiple types: operation type: ");
1887 print_generic_expr (vect_dump, type, TDF_SLIM);
1888 fprintf (vect_dump, ", operands types: ");
1889 print_generic_expr (vect_dump, TREE_TYPE (op1), TDF_SLIM);
1890 fprintf (vect_dump, ",");
1891 print_generic_expr (vect_dump, TREE_TYPE (op2), TDF_SLIM);
1892 if (op3)
1893 {
1894 fprintf (vect_dump, ",");
1895 print_generic_expr (vect_dump, TREE_TYPE (op3), TDF_SLIM);
1896 }
1897
1898 if (op4)
1899 {
1900 fprintf (vect_dump, ",");
1901 print_generic_expr (vect_dump, TREE_TYPE (op4), TDF_SLIM);
1902 }
1903 }
1904
1905 return NULL;
1906 }
1907
1908 /* Check that it's ok to change the order of the computation.
1909 Generally, when vectorizing a reduction we change the order of the
1910 computation. This may change the behavior of the program in some
1911 cases, so we need to check that this is ok. One exception is when
1912 vectorizing an outer-loop: the inner-loop is executed sequentially,
1913 and therefore vectorizing reductions in the inner-loop during
1914 outer-loop vectorization is safe. */
1915
1916 /* CHECKME: check for !flag_finite_math_only too? */
1917 if (SCALAR_FLOAT_TYPE_P (type) && !flag_associative_math
1918 && check_reduction)
1919 {
1920 /* Changing the order of operations changes the semantics. */
1921 if (vect_print_dump_info (REPORT_DETAILS))
1922 report_vect_op (def_stmt, "reduction: unsafe fp math optimization: ");
1923 return NULL;
1924 }
1925 else if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type)
1926 && check_reduction)
1927 {
1928 /* Changing the order of operations changes the semantics. */
1929 if (vect_print_dump_info (REPORT_DETAILS))
1930 report_vect_op (def_stmt, "reduction: unsafe int math optimization: ");
1931 return NULL;
1932 }
1933 else if (SAT_FIXED_POINT_TYPE_P (type) && check_reduction)
1934 {
1935 /* Changing the order of operations changes the semantics. */
1936 if (vect_print_dump_info (REPORT_DETAILS))
1937 report_vect_op (def_stmt,
1938 "reduction: unsafe fixed-point math optimization: ");
1939 return NULL;
1940 }
1941
1942 /* If we detected "res -= x[i]" earlier, rewrite it into
1943 "res += -x[i]" now. If this turns out to be useless reassoc
1944 will clean it up again. */
1945 if (orig_code == MINUS_EXPR)
1946 {
1947 tree rhs = gimple_assign_rhs2 (def_stmt);
1948 tree negrhs = make_ssa_name (SSA_NAME_VAR (rhs), NULL);
1949 gimple negate_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, negrhs,
1950 rhs, NULL);
1951 gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt);
1952 set_vinfo_for_stmt (negate_stmt, new_stmt_vec_info (negate_stmt,
1953 loop_info, NULL));
1954 gsi_insert_before (&gsi, negate_stmt, GSI_NEW_STMT);
1955 gimple_assign_set_rhs2 (def_stmt, negrhs);
1956 gimple_assign_set_rhs_code (def_stmt, PLUS_EXPR);
1957 update_stmt (def_stmt);
1958 }
1959
1960 /* Reduction is safe. We're dealing with one of the following:
1961 1) integer arithmetic and no trapv
1962 2) floating point arithmetic, and special flags permit this optimization
1963 3) nested cycle (i.e., outer loop vectorization). */
1964 if (TREE_CODE (op1) == SSA_NAME)
1965 def1 = SSA_NAME_DEF_STMT (op1);
1966
1967 if (TREE_CODE (op2) == SSA_NAME)
1968 def2 = SSA_NAME_DEF_STMT (op2);
1969
1970 if (code != COND_EXPR
1971 && (!def1 || !def2 || gimple_nop_p (def1) || gimple_nop_p (def2)))
1972 {
1973 if (vect_print_dump_info (REPORT_DETAILS))
1974 report_vect_op (def_stmt, "reduction: no defs for operands: ");
1975 return NULL;
1976 }
1977
1978 /* Check that one def is the reduction def, defined by PHI,
1979 the other def is either defined in the loop ("vect_internal_def"),
1980 or it's an induction (defined by a loop-header phi-node). */
1981
1982 if (def2 && def2 == phi
1983 && (code == COND_EXPR
1984 || (def1 && flow_bb_inside_loop_p (loop, gimple_bb (def1))
1985 && (is_gimple_assign (def1)
1986 || is_gimple_call (def1)
1987 || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def1))
1988 == vect_induction_def
1989 || (gimple_code (def1) == GIMPLE_PHI
1990 && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def1))
1991 == vect_internal_def
1992 && !is_loop_header_bb_p (gimple_bb (def1)))))))
1993 {
1994 if (vect_print_dump_info (REPORT_DETAILS))
1995 report_vect_op (def_stmt, "detected reduction: ");
1996 return def_stmt;
1997 }
1998 else if (def1 && def1 == phi
1999 && (code == COND_EXPR
2000 || (def2 && flow_bb_inside_loop_p (loop, gimple_bb (def2))
2001 && (is_gimple_assign (def2)
2002 || is_gimple_call (def2)
2003 || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
2004 == vect_induction_def
2005 || (gimple_code (def2) == GIMPLE_PHI
2006 && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
2007 == vect_internal_def
2008 && !is_loop_header_bb_p (gimple_bb (def2)))))))
2009 {
2010 if (check_reduction)
2011 {
2012 /* Swap operands (just for simplicity - so that the rest of the code
2013 can assume that the reduction variable is always the last (second)
2014 argument). */
2015 if (vect_print_dump_info (REPORT_DETAILS))
2016 report_vect_op (def_stmt,
2017 "detected reduction: need to swap operands: ");
2018
2019 swap_tree_operands (def_stmt, gimple_assign_rhs1_ptr (def_stmt),
2020 gimple_assign_rhs2_ptr (def_stmt));
2021 }
2022 else
2023 {
2024 if (vect_print_dump_info (REPORT_DETAILS))
2025 report_vect_op (def_stmt, "detected reduction: ");
2026 }
2027
2028 return def_stmt;
2029 }
2030 else
2031 {
2032 if (vect_print_dump_info (REPORT_DETAILS))
2033 report_vect_op (def_stmt, "reduction: unknown pattern: ");
2034
2035 return NULL;
2036 }
2037 }
2038
2039 /* Wrapper around vect_is_simple_reduction_1, that won't modify code
2040 in-place. Arguments as there. */
2041
2042 static gimple
2043 vect_is_simple_reduction (loop_vec_info loop_info, gimple phi,
2044 bool check_reduction, bool *double_reduc)
2045 {
2046 return vect_is_simple_reduction_1 (loop_info, phi, check_reduction,
2047 double_reduc, false);
2048 }
2049
2050 /* Wrapper around vect_is_simple_reduction_1, which will modify code
2051 in-place if it enables detection of more reductions. Arguments
2052 as there. */
2053
2054 gimple
2055 vect_force_simple_reduction (loop_vec_info loop_info, gimple phi,
2056 bool check_reduction, bool *double_reduc)
2057 {
2058 return vect_is_simple_reduction_1 (loop_info, phi, check_reduction,
2059 double_reduc, true);
2060 }
2061
2062 /* Calculate the cost of one scalar iteration of the loop. */
2063 int
2064 vect_get_single_scalar_iteraion_cost (loop_vec_info loop_vinfo)
2065 {
2066 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2067 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
2068 int nbbs = loop->num_nodes, factor, scalar_single_iter_cost = 0;
2069 int innerloop_iters, i, stmt_cost;
2070
2071 /* Count statements in scalar loop. Using this as scalar cost for a single
2072 iteration for now.
2073
2074 TODO: Add outer loop support.
2075
2076 TODO: Consider assigning different costs to different scalar
2077 statements. */
2078
2079 /* FORNOW. */
2080 innerloop_iters = 1;
2081 if (loop->inner)
2082 innerloop_iters = 50; /* FIXME */
2083
2084 for (i = 0; i < nbbs; i++)
2085 {
2086 gimple_stmt_iterator si;
2087 basic_block bb = bbs[i];
2088
2089 if (bb->loop_father == loop->inner)
2090 factor = innerloop_iters;
2091 else
2092 factor = 1;
2093
2094 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
2095 {
2096 gimple stmt = gsi_stmt (si);
2097 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2098
2099 if (!is_gimple_assign (stmt) && !is_gimple_call (stmt))
2100 continue;
2101
2102 /* Skip stmts that are not vectorized inside the loop. */
2103 if (stmt_info
2104 && !STMT_VINFO_RELEVANT_P (stmt_info)
2105 && (!STMT_VINFO_LIVE_P (stmt_info)
2106 || STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def))
2107 continue;
2108
2109 if (STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt)))
2110 {
2111 if (DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt))))
2112 stmt_cost = vect_get_cost (scalar_load);
2113 else
2114 stmt_cost = vect_get_cost (scalar_store);
2115 }
2116 else
2117 stmt_cost = vect_get_cost (scalar_stmt);
2118
2119 scalar_single_iter_cost += stmt_cost * factor;
2120 }
2121 }
2122 return scalar_single_iter_cost;
2123 }
2124
2125 /* Calculate cost of peeling the loop PEEL_ITERS_PROLOGUE times. */
2126 int
2127 vect_get_known_peeling_cost (loop_vec_info loop_vinfo, int peel_iters_prologue,
2128 int *peel_iters_epilogue,
2129 int scalar_single_iter_cost)
2130 {
2131 int peel_guard_costs = 0;
2132 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2133
2134 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
2135 {
2136 *peel_iters_epilogue = vf/2;
2137 if (vect_print_dump_info (REPORT_COST))
2138 fprintf (vect_dump, "cost model: "
2139 "epilogue peel iters set to vf/2 because "
2140 "loop iterations are unknown .");
2141
2142 /* If peeled iterations are known but number of scalar loop
2143 iterations are unknown, count a taken branch per peeled loop. */
2144 peel_guard_costs = 2 * vect_get_cost (cond_branch_taken);
2145 }
2146 else
2147 {
2148 int niters = LOOP_VINFO_INT_NITERS (loop_vinfo);
2149 peel_iters_prologue = niters < peel_iters_prologue ?
2150 niters : peel_iters_prologue;
2151 *peel_iters_epilogue = (niters - peel_iters_prologue) % vf;
2152 }
2153
2154 return (peel_iters_prologue * scalar_single_iter_cost)
2155 + (*peel_iters_epilogue * scalar_single_iter_cost)
2156 + peel_guard_costs;
2157 }
2158
2159 /* Function vect_estimate_min_profitable_iters
2160
2161 Return the number of iterations required for the vector version of the
2162 loop to be profitable relative to the cost of the scalar version of the
2163 loop.
2164
2165 TODO: Take profile info into account before making vectorization
2166 decisions, if available. */
2167
2168 int
2169 vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo)
2170 {
2171 int i;
2172 int min_profitable_iters;
2173 int peel_iters_prologue;
2174 int peel_iters_epilogue;
2175 int vec_inside_cost = 0;
2176 int vec_outside_cost = 0;
2177 int scalar_single_iter_cost = 0;
2178 int scalar_outside_cost = 0;
2179 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2180 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2181 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
2182 int nbbs = loop->num_nodes;
2183 int npeel = LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo);
2184 int peel_guard_costs = 0;
2185 int innerloop_iters = 0, factor;
2186 VEC (slp_instance, heap) *slp_instances;
2187 slp_instance instance;
2188
2189 /* Cost model disabled. */
2190 if (!flag_vect_cost_model)
2191 {
2192 if (vect_print_dump_info (REPORT_COST))
2193 fprintf (vect_dump, "cost model disabled.");
2194 return 0;
2195 }
2196
2197 /* Requires loop versioning tests to handle misalignment. */
2198 if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo))
2199 {
2200 /* FIXME: Make cost depend on complexity of individual check. */
2201 vec_outside_cost +=
2202 VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo));
2203 if (vect_print_dump_info (REPORT_COST))
2204 fprintf (vect_dump, "cost model: Adding cost of checks for loop "
2205 "versioning to treat misalignment.\n");
2206 }
2207
2208 /* Requires loop versioning with alias checks. */
2209 if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
2210 {
2211 /* FIXME: Make cost depend on complexity of individual check. */
2212 vec_outside_cost +=
2213 VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo));
2214 if (vect_print_dump_info (REPORT_COST))
2215 fprintf (vect_dump, "cost model: Adding cost of checks for loop "
2216 "versioning aliasing.\n");
2217 }
2218
2219 if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
2220 || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
2221 vec_outside_cost += vect_get_cost (cond_branch_taken);
2222
2223 /* Count statements in scalar loop. Using this as scalar cost for a single
2224 iteration for now.
2225
2226 TODO: Add outer loop support.
2227
2228 TODO: Consider assigning different costs to different scalar
2229 statements. */
2230
2231 /* FORNOW. */
2232 if (loop->inner)
2233 innerloop_iters = 50; /* FIXME */
2234
2235 for (i = 0; i < nbbs; i++)
2236 {
2237 gimple_stmt_iterator si;
2238 basic_block bb = bbs[i];
2239
2240 if (bb->loop_father == loop->inner)
2241 factor = innerloop_iters;
2242 else
2243 factor = 1;
2244
2245 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
2246 {
2247 gimple stmt = gsi_stmt (si);
2248 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2249 /* Skip stmts that are not vectorized inside the loop. */
2250 if (!STMT_VINFO_RELEVANT_P (stmt_info)
2251 && (!STMT_VINFO_LIVE_P (stmt_info)
2252 || STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def))
2253 continue;
2254 vec_inside_cost += STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info) * factor;
2255 /* FIXME: for stmts in the inner-loop in outer-loop vectorization,
2256 some of the "outside" costs are generated inside the outer-loop. */
2257 vec_outside_cost += STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info);
2258 }
2259 }
2260
2261 scalar_single_iter_cost = vect_get_single_scalar_iteraion_cost (loop_vinfo);
2262
2263 /* Add additional cost for the peeled instructions in prologue and epilogue
2264 loop.
2265
2266 FORNOW: If we don't know the value of peel_iters for prologue or epilogue
2267 at compile-time - we assume it's vf/2 (the worst would be vf-1).
2268
2269 TODO: Build an expression that represents peel_iters for prologue and
2270 epilogue to be used in a run-time test. */
2271
2272 if (npeel < 0)
2273 {
2274 peel_iters_prologue = vf/2;
2275 if (vect_print_dump_info (REPORT_COST))
2276 fprintf (vect_dump, "cost model: "
2277 "prologue peel iters set to vf/2.");
2278
2279 /* If peeling for alignment is unknown, loop bound of main loop becomes
2280 unknown. */
2281 peel_iters_epilogue = vf/2;
2282 if (vect_print_dump_info (REPORT_COST))
2283 fprintf (vect_dump, "cost model: "
2284 "epilogue peel iters set to vf/2 because "
2285 "peeling for alignment is unknown .");
2286
2287 /* If peeled iterations are unknown, count a taken branch and a not taken
2288 branch per peeled loop. Even if scalar loop iterations are known,
2289 vector iterations are not known since peeled prologue iterations are
2290 not known. Hence guards remain the same. */
2291 peel_guard_costs += 2 * (vect_get_cost (cond_branch_taken)
2292 + vect_get_cost (cond_branch_not_taken));
2293 vec_outside_cost += (peel_iters_prologue * scalar_single_iter_cost)
2294 + (peel_iters_epilogue * scalar_single_iter_cost)
2295 + peel_guard_costs;
2296 }
2297 else
2298 {
2299 peel_iters_prologue = npeel;
2300 vec_outside_cost += vect_get_known_peeling_cost (loop_vinfo,
2301 peel_iters_prologue, &peel_iters_epilogue,
2302 scalar_single_iter_cost);
2303 }
2304
2305 /* FORNOW: The scalar outside cost is incremented in one of the
2306 following ways:
2307
2308 1. The vectorizer checks for alignment and aliasing and generates
2309 a condition that allows dynamic vectorization. A cost model
2310 check is ANDED with the versioning condition. Hence scalar code
2311 path now has the added cost of the versioning check.
2312
2313 if (cost > th & versioning_check)
2314 jmp to vector code
2315
2316 Hence run-time scalar is incremented by not-taken branch cost.
2317
2318 2. The vectorizer then checks if a prologue is required. If the
2319 cost model check was not done before during versioning, it has to
2320 be done before the prologue check.
2321
2322 if (cost <= th)
2323 prologue = scalar_iters
2324 if (prologue == 0)
2325 jmp to vector code
2326 else
2327 execute prologue
2328 if (prologue == num_iters)
2329 go to exit
2330
2331 Hence the run-time scalar cost is incremented by a taken branch,
2332 plus a not-taken branch, plus a taken branch cost.
2333
2334 3. The vectorizer then checks if an epilogue is required. If the
2335 cost model check was not done before during prologue check, it
2336 has to be done with the epilogue check.
2337
2338 if (prologue == 0)
2339 jmp to vector code
2340 else
2341 execute prologue
2342 if (prologue == num_iters)
2343 go to exit
2344 vector code:
2345 if ((cost <= th) | (scalar_iters-prologue-epilogue == 0))
2346 jmp to epilogue
2347
2348 Hence the run-time scalar cost should be incremented by 2 taken
2349 branches.
2350
2351 TODO: The back end may reorder the BBS's differently and reverse
2352 conditions/branch directions. Change the estimates below to
2353 something more reasonable. */
2354
2355 /* If the number of iterations is known and we do not do versioning, we can
2356 decide whether to vectorize at compile time. Hence the scalar version
2357 do not carry cost model guard costs. */
2358 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
2359 || LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
2360 || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
2361 {
2362 /* Cost model check occurs at versioning. */
2363 if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
2364 || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
2365 scalar_outside_cost += vect_get_cost (cond_branch_not_taken);
2366 else
2367 {
2368 /* Cost model check occurs at prologue generation. */
2369 if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) < 0)
2370 scalar_outside_cost += 2 * vect_get_cost (cond_branch_taken)
2371 + vect_get_cost (cond_branch_not_taken);
2372 /* Cost model check occurs at epilogue generation. */
2373 else
2374 scalar_outside_cost += 2 * vect_get_cost (cond_branch_taken);
2375 }
2376 }
2377
2378 /* Add SLP costs. */
2379 slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
2380 FOR_EACH_VEC_ELT (slp_instance, slp_instances, i, instance)
2381 {
2382 vec_outside_cost += SLP_INSTANCE_OUTSIDE_OF_LOOP_COST (instance);
2383 vec_inside_cost += SLP_INSTANCE_INSIDE_OF_LOOP_COST (instance);
2384 }
2385
2386 /* Calculate number of iterations required to make the vector version
2387 profitable, relative to the loop bodies only. The following condition
2388 must hold true:
2389 SIC * niters + SOC > VIC * ((niters-PL_ITERS-EP_ITERS)/VF) + VOC
2390 where
2391 SIC = scalar iteration cost, VIC = vector iteration cost,
2392 VOC = vector outside cost, VF = vectorization factor,
2393 PL_ITERS = prologue iterations, EP_ITERS= epilogue iterations
2394 SOC = scalar outside cost for run time cost model check. */
2395
2396 if ((scalar_single_iter_cost * vf) > vec_inside_cost)
2397 {
2398 if (vec_outside_cost <= 0)
2399 min_profitable_iters = 1;
2400 else
2401 {
2402 min_profitable_iters = ((vec_outside_cost - scalar_outside_cost) * vf
2403 - vec_inside_cost * peel_iters_prologue
2404 - vec_inside_cost * peel_iters_epilogue)
2405 / ((scalar_single_iter_cost * vf)
2406 - vec_inside_cost);
2407
2408 if ((scalar_single_iter_cost * vf * min_profitable_iters)
2409 <= ((vec_inside_cost * min_profitable_iters)
2410 + ((vec_outside_cost - scalar_outside_cost) * vf)))
2411 min_profitable_iters++;
2412 }
2413 }
2414 /* vector version will never be profitable. */
2415 else
2416 {
2417 if (vect_print_dump_info (REPORT_COST))
2418 fprintf (vect_dump, "cost model: the vector iteration cost = %d "
2419 "divided by the scalar iteration cost = %d "
2420 "is greater or equal to the vectorization factor = %d.",
2421 vec_inside_cost, scalar_single_iter_cost, vf);
2422 return -1;
2423 }
2424
2425 if (vect_print_dump_info (REPORT_COST))
2426 {
2427 fprintf (vect_dump, "Cost model analysis: \n");
2428 fprintf (vect_dump, " Vector inside of loop cost: %d\n",
2429 vec_inside_cost);
2430 fprintf (vect_dump, " Vector outside of loop cost: %d\n",
2431 vec_outside_cost);
2432 fprintf (vect_dump, " Scalar iteration cost: %d\n",
2433 scalar_single_iter_cost);
2434 fprintf (vect_dump, " Scalar outside cost: %d\n", scalar_outside_cost);
2435 fprintf (vect_dump, " prologue iterations: %d\n",
2436 peel_iters_prologue);
2437 fprintf (vect_dump, " epilogue iterations: %d\n",
2438 peel_iters_epilogue);
2439 fprintf (vect_dump, " Calculated minimum iters for profitability: %d\n",
2440 min_profitable_iters);
2441 }
2442
2443 min_profitable_iters =
2444 min_profitable_iters < vf ? vf : min_profitable_iters;
2445
2446 /* Because the condition we create is:
2447 if (niters <= min_profitable_iters)
2448 then skip the vectorized loop. */
2449 min_profitable_iters--;
2450
2451 if (vect_print_dump_info (REPORT_COST))
2452 fprintf (vect_dump, " Profitability threshold = %d\n",
2453 min_profitable_iters);
2454
2455 return min_profitable_iters;
2456 }
2457
2458
2459 /* TODO: Close dependency between vect_model_*_cost and vectorizable_*
2460 functions. Design better to avoid maintenance issues. */
2461
2462 /* Function vect_model_reduction_cost.
2463
2464 Models cost for a reduction operation, including the vector ops
2465 generated within the strip-mine loop, the initial definition before
2466 the loop, and the epilogue code that must be generated. */
2467
2468 static bool
2469 vect_model_reduction_cost (stmt_vec_info stmt_info, enum tree_code reduc_code,
2470 int ncopies)
2471 {
2472 int outer_cost = 0;
2473 enum tree_code code;
2474 optab optab;
2475 tree vectype;
2476 gimple stmt, orig_stmt;
2477 tree reduction_op;
2478 enum machine_mode mode;
2479 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2480 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2481
2482
2483 /* Cost of reduction op inside loop. */
2484 STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info)
2485 += ncopies * vect_get_cost (vector_stmt);
2486
2487 stmt = STMT_VINFO_STMT (stmt_info);
2488
2489 switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
2490 {
2491 case GIMPLE_SINGLE_RHS:
2492 gcc_assert (TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt)) == ternary_op);
2493 reduction_op = TREE_OPERAND (gimple_assign_rhs1 (stmt), 2);
2494 break;
2495 case GIMPLE_UNARY_RHS:
2496 reduction_op = gimple_assign_rhs1 (stmt);
2497 break;
2498 case GIMPLE_BINARY_RHS:
2499 reduction_op = gimple_assign_rhs2 (stmt);
2500 break;
2501 case GIMPLE_TERNARY_RHS:
2502 reduction_op = gimple_assign_rhs3 (stmt);
2503 break;
2504 default:
2505 gcc_unreachable ();
2506 }
2507
2508 vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op));
2509 if (!vectype)
2510 {
2511 if (vect_print_dump_info (REPORT_COST))
2512 {
2513 fprintf (vect_dump, "unsupported data-type ");
2514 print_generic_expr (vect_dump, TREE_TYPE (reduction_op), TDF_SLIM);
2515 }
2516 return false;
2517 }
2518
2519 mode = TYPE_MODE (vectype);
2520 orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
2521
2522 if (!orig_stmt)
2523 orig_stmt = STMT_VINFO_STMT (stmt_info);
2524
2525 code = gimple_assign_rhs_code (orig_stmt);
2526
2527 /* Add in cost for initial definition. */
2528 outer_cost += vect_get_cost (scalar_to_vec);
2529
2530 /* Determine cost of epilogue code.
2531
2532 We have a reduction operator that will reduce the vector in one statement.
2533 Also requires scalar extract. */
2534
2535 if (!nested_in_vect_loop_p (loop, orig_stmt))
2536 {
2537 if (reduc_code != ERROR_MARK)
2538 outer_cost += vect_get_cost (vector_stmt)
2539 + vect_get_cost (vec_to_scalar);
2540 else
2541 {
2542 int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
2543 tree bitsize =
2544 TYPE_SIZE (TREE_TYPE (gimple_assign_lhs (orig_stmt)));
2545 int element_bitsize = tree_low_cst (bitsize, 1);
2546 int nelements = vec_size_in_bits / element_bitsize;
2547
2548 optab = optab_for_tree_code (code, vectype, optab_default);
2549
2550 /* We have a whole vector shift available. */
2551 if (VECTOR_MODE_P (mode)
2552 && optab_handler (optab, mode) != CODE_FOR_nothing
2553 && optab_handler (vec_shr_optab, mode) != CODE_FOR_nothing)
2554 /* Final reduction via vector shifts and the reduction operator. Also
2555 requires scalar extract. */
2556 outer_cost += ((exact_log2(nelements) * 2)
2557 * vect_get_cost (vector_stmt)
2558 + vect_get_cost (vec_to_scalar));
2559 else
2560 /* Use extracts and reduction op for final reduction. For N elements,
2561 we have N extracts and N-1 reduction ops. */
2562 outer_cost += ((nelements + nelements - 1)
2563 * vect_get_cost (vector_stmt));
2564 }
2565 }
2566
2567 STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info) = outer_cost;
2568
2569 if (vect_print_dump_info (REPORT_COST))
2570 fprintf (vect_dump, "vect_model_reduction_cost: inside_cost = %d, "
2571 "outside_cost = %d .", STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info),
2572 STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info));
2573
2574 return true;
2575 }
2576
2577
2578 /* Function vect_model_induction_cost.
2579
2580 Models cost for induction operations. */
2581
2582 static void
2583 vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies)
2584 {
2585 /* loop cost for vec_loop. */
2586 STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info)
2587 = ncopies * vect_get_cost (vector_stmt);
2588 /* prologue cost for vec_init and vec_step. */
2589 STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info)
2590 = 2 * vect_get_cost (scalar_to_vec);
2591
2592 if (vect_print_dump_info (REPORT_COST))
2593 fprintf (vect_dump, "vect_model_induction_cost: inside_cost = %d, "
2594 "outside_cost = %d .", STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info),
2595 STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info));
2596 }
2597
2598
2599 /* Function get_initial_def_for_induction
2600
2601 Input:
2602 STMT - a stmt that performs an induction operation in the loop.
2603 IV_PHI - the initial value of the induction variable
2604
2605 Output:
2606 Return a vector variable, initialized with the first VF values of
2607 the induction variable. E.g., for an iv with IV_PHI='X' and
2608 evolution S, for a vector of 4 units, we want to return:
2609 [X, X + S, X + 2*S, X + 3*S]. */
2610
2611 static tree
2612 get_initial_def_for_induction (gimple iv_phi)
2613 {
2614 stmt_vec_info stmt_vinfo = vinfo_for_stmt (iv_phi);
2615 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
2616 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2617 tree scalar_type;
2618 tree vectype;
2619 int nunits;
2620 edge pe = loop_preheader_edge (loop);
2621 struct loop *iv_loop;
2622 basic_block new_bb;
2623 tree vec, vec_init, vec_step, t;
2624 tree access_fn;
2625 tree new_var;
2626 tree new_name;
2627 gimple init_stmt, induction_phi, new_stmt;
2628 tree induc_def, vec_def, vec_dest;
2629 tree init_expr, step_expr;
2630 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2631 int i;
2632 bool ok;
2633 int ncopies;
2634 tree expr;
2635 stmt_vec_info phi_info = vinfo_for_stmt (iv_phi);
2636 bool nested_in_vect_loop = false;
2637 gimple_seq stmts = NULL;
2638 imm_use_iterator imm_iter;
2639 use_operand_p use_p;
2640 gimple exit_phi;
2641 edge latch_e;
2642 tree loop_arg;
2643 gimple_stmt_iterator si;
2644 basic_block bb = gimple_bb (iv_phi);
2645 tree stepvectype;
2646 tree resvectype;
2647
2648 /* Is phi in an inner-loop, while vectorizing an enclosing outer-loop? */
2649 if (nested_in_vect_loop_p (loop, iv_phi))
2650 {
2651 nested_in_vect_loop = true;
2652 iv_loop = loop->inner;
2653 }
2654 else
2655 iv_loop = loop;
2656 gcc_assert (iv_loop == (gimple_bb (iv_phi))->loop_father);
2657
2658 latch_e = loop_latch_edge (iv_loop);
2659 loop_arg = PHI_ARG_DEF_FROM_EDGE (iv_phi, latch_e);
2660
2661 access_fn = analyze_scalar_evolution (iv_loop, PHI_RESULT (iv_phi));
2662 gcc_assert (access_fn);
2663 STRIP_NOPS (access_fn);
2664 ok = vect_is_simple_iv_evolution (iv_loop->num, access_fn,
2665 &init_expr, &step_expr);
2666 gcc_assert (ok);
2667 pe = loop_preheader_edge (iv_loop);
2668
2669 scalar_type = TREE_TYPE (init_expr);
2670 vectype = get_vectype_for_scalar_type (scalar_type);
2671 resvectype = get_vectype_for_scalar_type (TREE_TYPE (PHI_RESULT (iv_phi)));
2672 gcc_assert (vectype);
2673 nunits = TYPE_VECTOR_SUBPARTS (vectype);
2674 ncopies = vf / nunits;
2675
2676 gcc_assert (phi_info);
2677 gcc_assert (ncopies >= 1);
2678
2679 /* Find the first insertion point in the BB. */
2680 si = gsi_after_labels (bb);
2681
2682 /* Create the vector that holds the initial_value of the induction. */
2683 if (nested_in_vect_loop)
2684 {
2685 /* iv_loop is nested in the loop to be vectorized. init_expr had already
2686 been created during vectorization of previous stmts. We obtain it
2687 from the STMT_VINFO_VEC_STMT of the defining stmt. */
2688 tree iv_def = PHI_ARG_DEF_FROM_EDGE (iv_phi,
2689 loop_preheader_edge (iv_loop));
2690 vec_init = vect_get_vec_def_for_operand (iv_def, iv_phi, NULL);
2691 }
2692 else
2693 {
2694 /* iv_loop is the loop to be vectorized. Create:
2695 vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr) */
2696 new_var = vect_get_new_vect_var (scalar_type, vect_scalar_var, "var_");
2697 add_referenced_var (new_var);
2698
2699 new_name = force_gimple_operand (init_expr, &stmts, false, new_var);
2700 if (stmts)
2701 {
2702 new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
2703 gcc_assert (!new_bb);
2704 }
2705
2706 t = NULL_TREE;
2707 t = tree_cons (NULL_TREE, new_name, t);
2708 for (i = 1; i < nunits; i++)
2709 {
2710 /* Create: new_name_i = new_name + step_expr */
2711 enum tree_code code = POINTER_TYPE_P (scalar_type)
2712 ? POINTER_PLUS_EXPR : PLUS_EXPR;
2713 init_stmt = gimple_build_assign_with_ops (code, new_var,
2714 new_name, step_expr);
2715 new_name = make_ssa_name (new_var, init_stmt);
2716 gimple_assign_set_lhs (init_stmt, new_name);
2717
2718 new_bb = gsi_insert_on_edge_immediate (pe, init_stmt);
2719 gcc_assert (!new_bb);
2720
2721 if (vect_print_dump_info (REPORT_DETAILS))
2722 {
2723 fprintf (vect_dump, "created new init_stmt: ");
2724 print_gimple_stmt (vect_dump, init_stmt, 0, TDF_SLIM);
2725 }
2726 t = tree_cons (NULL_TREE, new_name, t);
2727 }
2728 /* Create a vector from [new_name_0, new_name_1, ..., new_name_nunits-1] */
2729 vec = build_constructor_from_list (vectype, nreverse (t));
2730 vec_init = vect_init_vector (iv_phi, vec, vectype, NULL);
2731 }
2732
2733
2734 /* Create the vector that holds the step of the induction. */
2735 if (nested_in_vect_loop)
2736 /* iv_loop is nested in the loop to be vectorized. Generate:
2737 vec_step = [S, S, S, S] */
2738 new_name = step_expr;
2739 else
2740 {
2741 /* iv_loop is the loop to be vectorized. Generate:
2742 vec_step = [VF*S, VF*S, VF*S, VF*S] */
2743 expr = build_int_cst (TREE_TYPE (step_expr), vf);
2744 new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
2745 expr, step_expr);
2746 }
2747
2748 t = unshare_expr (new_name);
2749 gcc_assert (CONSTANT_CLASS_P (new_name));
2750 stepvectype = get_vectype_for_scalar_type (TREE_TYPE (new_name));
2751 gcc_assert (stepvectype);
2752 vec = build_vector_from_val (stepvectype, t);
2753 vec_step = vect_init_vector (iv_phi, vec, stepvectype, NULL);
2754
2755
2756 /* Create the following def-use cycle:
2757 loop prolog:
2758 vec_init = ...
2759 vec_step = ...
2760 loop:
2761 vec_iv = PHI <vec_init, vec_loop>
2762 ...
2763 STMT
2764 ...
2765 vec_loop = vec_iv + vec_step; */
2766
2767 /* Create the induction-phi that defines the induction-operand. */
2768 vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");
2769 add_referenced_var (vec_dest);
2770 induction_phi = create_phi_node (vec_dest, iv_loop->header);
2771 set_vinfo_for_stmt (induction_phi,
2772 new_stmt_vec_info (induction_phi, loop_vinfo, NULL));
2773 induc_def = PHI_RESULT (induction_phi);
2774
2775 /* Create the iv update inside the loop */
2776 new_stmt = gimple_build_assign_with_ops (PLUS_EXPR, vec_dest,
2777 induc_def, vec_step);
2778 vec_def = make_ssa_name (vec_dest, new_stmt);
2779 gimple_assign_set_lhs (new_stmt, vec_def);
2780 gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
2781 set_vinfo_for_stmt (new_stmt, new_stmt_vec_info (new_stmt, loop_vinfo,
2782 NULL));
2783
2784 /* Set the arguments of the phi node: */
2785 add_phi_arg (induction_phi, vec_init, pe, UNKNOWN_LOCATION);
2786 add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop),
2787 UNKNOWN_LOCATION);
2788
2789
2790 /* In case that vectorization factor (VF) is bigger than the number
2791 of elements that we can fit in a vectype (nunits), we have to generate
2792 more than one vector stmt - i.e - we need to "unroll" the
2793 vector stmt by a factor VF/nunits. For more details see documentation
2794 in vectorizable_operation. */
2795
2796 if (ncopies > 1)
2797 {
2798 stmt_vec_info prev_stmt_vinfo;
2799 /* FORNOW. This restriction should be relaxed. */
2800 gcc_assert (!nested_in_vect_loop);
2801
2802 /* Create the vector that holds the step of the induction. */
2803 expr = build_int_cst (TREE_TYPE (step_expr), nunits);
2804 new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
2805 expr, step_expr);
2806 t = unshare_expr (new_name);
2807 gcc_assert (CONSTANT_CLASS_P (new_name));
2808 vec = build_vector_from_val (stepvectype, t);
2809 vec_step = vect_init_vector (iv_phi, vec, stepvectype, NULL);
2810
2811 vec_def = induc_def;
2812 prev_stmt_vinfo = vinfo_for_stmt (induction_phi);
2813 for (i = 1; i < ncopies; i++)
2814 {
2815 /* vec_i = vec_prev + vec_step */
2816 new_stmt = gimple_build_assign_with_ops (PLUS_EXPR, vec_dest,
2817 vec_def, vec_step);
2818 vec_def = make_ssa_name (vec_dest, new_stmt);
2819 gimple_assign_set_lhs (new_stmt, vec_def);
2820
2821 gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
2822 if (!useless_type_conversion_p (resvectype, vectype))
2823 {
2824 new_stmt = gimple_build_assign_with_ops
2825 (VIEW_CONVERT_EXPR,
2826 vect_get_new_vect_var (resvectype, vect_simple_var,
2827 "vec_iv_"),
2828 build1 (VIEW_CONVERT_EXPR, resvectype,
2829 gimple_assign_lhs (new_stmt)), NULL_TREE);
2830 gimple_assign_set_lhs (new_stmt,
2831 make_ssa_name
2832 (gimple_assign_lhs (new_stmt), new_stmt));
2833 gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
2834 }
2835 set_vinfo_for_stmt (new_stmt,
2836 new_stmt_vec_info (new_stmt, loop_vinfo, NULL));
2837 STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt;
2838 prev_stmt_vinfo = vinfo_for_stmt (new_stmt);
2839 }
2840 }
2841
2842 if (nested_in_vect_loop)
2843 {
2844 /* Find the loop-closed exit-phi of the induction, and record
2845 the final vector of induction results: */
2846 exit_phi = NULL;
2847 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, loop_arg)
2848 {
2849 if (!flow_bb_inside_loop_p (iv_loop, gimple_bb (USE_STMT (use_p))))
2850 {
2851 exit_phi = USE_STMT (use_p);
2852 break;
2853 }
2854 }
2855 if (exit_phi)
2856 {
2857 stmt_vec_info stmt_vinfo = vinfo_for_stmt (exit_phi);
2858 /* FORNOW. Currently not supporting the case that an inner-loop induction
2859 is not used in the outer-loop (i.e. only outside the outer-loop). */
2860 gcc_assert (STMT_VINFO_RELEVANT_P (stmt_vinfo)
2861 && !STMT_VINFO_LIVE_P (stmt_vinfo));
2862
2863 STMT_VINFO_VEC_STMT (stmt_vinfo) = new_stmt;
2864 if (vect_print_dump_info (REPORT_DETAILS))
2865 {
2866 fprintf (vect_dump, "vector of inductions after inner-loop:");
2867 print_gimple_stmt (vect_dump, new_stmt, 0, TDF_SLIM);
2868 }
2869 }
2870 }
2871
2872
2873 if (vect_print_dump_info (REPORT_DETAILS))
2874 {
2875 fprintf (vect_dump, "transform induction: created def-use cycle: ");
2876 print_gimple_stmt (vect_dump, induction_phi, 0, TDF_SLIM);
2877 fprintf (vect_dump, "\n");
2878 print_gimple_stmt (vect_dump, SSA_NAME_DEF_STMT (vec_def), 0, TDF_SLIM);
2879 }
2880
2881 STMT_VINFO_VEC_STMT (phi_info) = induction_phi;
2882 if (!useless_type_conversion_p (resvectype, vectype))
2883 {
2884 new_stmt = gimple_build_assign_with_ops
2885 (VIEW_CONVERT_EXPR,
2886 vect_get_new_vect_var (resvectype, vect_simple_var, "vec_iv_"),
2887 build1 (VIEW_CONVERT_EXPR, resvectype, induc_def), NULL_TREE);
2888 induc_def = make_ssa_name (gimple_assign_lhs (new_stmt), new_stmt);
2889 gimple_assign_set_lhs (new_stmt, induc_def);
2890 si = gsi_start_bb (bb);
2891 gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
2892 set_vinfo_for_stmt (new_stmt,
2893 new_stmt_vec_info (new_stmt, loop_vinfo, NULL));
2894 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (new_stmt))
2895 = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (induction_phi));
2896 }
2897
2898 return induc_def;
2899 }
2900
2901
2902 /* Function get_initial_def_for_reduction
2903
2904 Input:
2905 STMT - a stmt that performs a reduction operation in the loop.
2906 INIT_VAL - the initial value of the reduction variable
2907
2908 Output:
2909 ADJUSTMENT_DEF - a tree that holds a value to be added to the final result
2910 of the reduction (used for adjusting the epilog - see below).
2911 Return a vector variable, initialized according to the operation that STMT
2912 performs. This vector will be used as the initial value of the
2913 vector of partial results.
2914
2915 Option1 (adjust in epilog): Initialize the vector as follows:
2916 add/bit or/xor: [0,0,...,0,0]
2917 mult/bit and: [1,1,...,1,1]
2918 min/max/cond_expr: [init_val,init_val,..,init_val,init_val]
2919 and when necessary (e.g. add/mult case) let the caller know
2920 that it needs to adjust the result by init_val.
2921
2922 Option2: Initialize the vector as follows:
2923 add/bit or/xor: [init_val,0,0,...,0]
2924 mult/bit and: [init_val,1,1,...,1]
2925 min/max/cond_expr: [init_val,init_val,...,init_val]
2926 and no adjustments are needed.
2927
2928 For example, for the following code:
2929
2930 s = init_val;
2931 for (i=0;i<n;i++)
2932 s = s + a[i];
2933
2934 STMT is 's = s + a[i]', and the reduction variable is 's'.
2935 For a vector of 4 units, we want to return either [0,0,0,init_val],
2936 or [0,0,0,0] and let the caller know that it needs to adjust
2937 the result at the end by 'init_val'.
2938
2939 FORNOW, we are using the 'adjust in epilog' scheme, because this way the
2940 initialization vector is simpler (same element in all entries), if
2941 ADJUSTMENT_DEF is not NULL, and Option2 otherwise.
2942
2943 A cost model should help decide between these two schemes. */
2944
2945 tree
2946 get_initial_def_for_reduction (gimple stmt, tree init_val,
2947 tree *adjustment_def)
2948 {
2949 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
2950 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
2951 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2952 tree scalar_type = TREE_TYPE (init_val);
2953 tree vectype = get_vectype_for_scalar_type (scalar_type);
2954 int nunits;
2955 enum tree_code code = gimple_assign_rhs_code (stmt);
2956 tree def_for_init;
2957 tree init_def;
2958 tree t = NULL_TREE;
2959 int i;
2960 bool nested_in_vect_loop = false;
2961 tree init_value;
2962 REAL_VALUE_TYPE real_init_val = dconst0;
2963 int int_init_val = 0;
2964 gimple def_stmt = NULL;
2965
2966 gcc_assert (vectype);
2967 nunits = TYPE_VECTOR_SUBPARTS (vectype);
2968
2969 gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type)
2970 || SCALAR_FLOAT_TYPE_P (scalar_type));
2971
2972 if (nested_in_vect_loop_p (loop, stmt))
2973 nested_in_vect_loop = true;
2974 else
2975 gcc_assert (loop == (gimple_bb (stmt))->loop_father);
2976
2977 /* In case of double reduction we only create a vector variable to be put
2978 in the reduction phi node. The actual statement creation is done in
2979 vect_create_epilog_for_reduction. */
2980 if (adjustment_def && nested_in_vect_loop
2981 && TREE_CODE (init_val) == SSA_NAME
2982 && (def_stmt = SSA_NAME_DEF_STMT (init_val))
2983 && gimple_code (def_stmt) == GIMPLE_PHI
2984 && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
2985 && vinfo_for_stmt (def_stmt)
2986 && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt))
2987 == vect_double_reduction_def)
2988 {
2989 *adjustment_def = NULL;
2990 return vect_create_destination_var (init_val, vectype);
2991 }
2992
2993 if (TREE_CONSTANT (init_val))
2994 {
2995 if (SCALAR_FLOAT_TYPE_P (scalar_type))
2996 init_value = build_real (scalar_type, TREE_REAL_CST (init_val));
2997 else
2998 init_value = build_int_cst (scalar_type, TREE_INT_CST_LOW (init_val));
2999 }
3000 else
3001 init_value = init_val;
3002
3003 switch (code)
3004 {
3005 case WIDEN_SUM_EXPR:
3006 case DOT_PROD_EXPR:
3007 case PLUS_EXPR:
3008 case MINUS_EXPR:
3009 case BIT_IOR_EXPR:
3010 case BIT_XOR_EXPR:
3011 case MULT_EXPR:
3012 case BIT_AND_EXPR:
3013 /* ADJUSMENT_DEF is NULL when called from
3014 vect_create_epilog_for_reduction to vectorize double reduction. */
3015 if (adjustment_def)
3016 {
3017 if (nested_in_vect_loop)
3018 *adjustment_def = vect_get_vec_def_for_operand (init_val, stmt,
3019 NULL);
3020 else
3021 *adjustment_def = init_val;
3022 }
3023
3024 if (code == MULT_EXPR)
3025 {
3026 real_init_val = dconst1;
3027 int_init_val = 1;
3028 }
3029
3030 if (code == BIT_AND_EXPR)
3031 int_init_val = -1;
3032
3033 if (SCALAR_FLOAT_TYPE_P (scalar_type))
3034 def_for_init = build_real (scalar_type, real_init_val);
3035 else
3036 def_for_init = build_int_cst (scalar_type, int_init_val);
3037
3038 /* Create a vector of '0' or '1' except the first element. */
3039 for (i = nunits - 2; i >= 0; --i)
3040 t = tree_cons (NULL_TREE, def_for_init, t);
3041
3042 /* Option1: the first element is '0' or '1' as well. */
3043 if (adjustment_def)
3044 {
3045 t = tree_cons (NULL_TREE, def_for_init, t);
3046 init_def = build_vector (vectype, t);
3047 break;
3048 }
3049
3050 /* Option2: the first element is INIT_VAL. */
3051 t = tree_cons (NULL_TREE, init_value, t);
3052 if (TREE_CONSTANT (init_val))
3053 init_def = build_vector (vectype, t);
3054 else
3055 init_def = build_constructor_from_list (vectype, t);
3056
3057 break;
3058
3059 case MIN_EXPR:
3060 case MAX_EXPR:
3061 case COND_EXPR:
3062 if (adjustment_def)
3063 {
3064 *adjustment_def = NULL_TREE;
3065 init_def = vect_get_vec_def_for_operand (init_val, stmt, NULL);
3066 break;
3067 }
3068
3069 init_def = build_vector_from_val (vectype, init_value);
3070 break;
3071
3072 default:
3073 gcc_unreachable ();
3074 }
3075
3076 return init_def;
3077 }
3078
3079
3080 /* Function vect_create_epilog_for_reduction
3081
3082 Create code at the loop-epilog to finalize the result of a reduction
3083 computation.
3084
3085 VECT_DEFS is list of vector of partial results, i.e., the lhs's of vector
3086 reduction statements.
3087 STMT is the scalar reduction stmt that is being vectorized.
3088 NCOPIES is > 1 in case the vectorization factor (VF) is bigger than the
3089 number of elements that we can fit in a vectype (nunits). In this case
3090 we have to generate more than one vector stmt - i.e - we need to "unroll"
3091 the vector stmt by a factor VF/nunits. For more details see documentation
3092 in vectorizable_operation.
3093 REDUC_CODE is the tree-code for the epilog reduction.
3094 REDUCTION_PHIS is a list of the phi-nodes that carry the reduction
3095 computation.
3096 REDUC_INDEX is the index of the operand in the right hand side of the
3097 statement that is defined by REDUCTION_PHI.
3098 DOUBLE_REDUC is TRUE if double reduction phi nodes should be handled.
3099 SLP_NODE is an SLP node containing a group of reduction statements. The
3100 first one in this group is STMT.
3101
3102 This function:
3103 1. Creates the reduction def-use cycles: sets the arguments for
3104 REDUCTION_PHIS:
3105 The loop-entry argument is the vectorized initial-value of the reduction.
3106 The loop-latch argument is taken from VECT_DEFS - the vector of partial
3107 sums.
3108 2. "Reduces" each vector of partial results VECT_DEFS into a single result,
3109 by applying the operation specified by REDUC_CODE if available, or by
3110 other means (whole-vector shifts or a scalar loop).
3111 The function also creates a new phi node at the loop exit to preserve
3112 loop-closed form, as illustrated below.
3113
3114 The flow at the entry to this function:
3115
3116 loop:
3117 vec_def = phi <null, null> # REDUCTION_PHI
3118 VECT_DEF = vector_stmt # vectorized form of STMT
3119 s_loop = scalar_stmt # (scalar) STMT
3120 loop_exit:
3121 s_out0 = phi <s_loop> # (scalar) EXIT_PHI
3122 use <s_out0>
3123 use <s_out0>
3124
3125 The above is transformed by this function into:
3126
3127 loop:
3128 vec_def = phi <vec_init, VECT_DEF> # REDUCTION_PHI
3129 VECT_DEF = vector_stmt # vectorized form of STMT
3130 s_loop = scalar_stmt # (scalar) STMT
3131 loop_exit:
3132 s_out0 = phi <s_loop> # (scalar) EXIT_PHI
3133 v_out1 = phi <VECT_DEF> # NEW_EXIT_PHI
3134 v_out2 = reduce <v_out1>
3135 s_out3 = extract_field <v_out2, 0>
3136 s_out4 = adjust_result <s_out3>
3137 use <s_out4>
3138 use <s_out4>
3139 */
3140
3141 static void
3142 vect_create_epilog_for_reduction (VEC (tree, heap) *vect_defs, gimple stmt,
3143 int ncopies, enum tree_code reduc_code,
3144 VEC (gimple, heap) *reduction_phis,
3145 int reduc_index, bool double_reduc,
3146 slp_tree slp_node)
3147 {
3148 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3149 stmt_vec_info prev_phi_info;
3150 tree vectype;
3151 enum machine_mode mode;
3152 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3153 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo), *outer_loop = NULL;
3154 basic_block exit_bb;
3155 tree scalar_dest;
3156 tree scalar_type;
3157 gimple new_phi = NULL, phi;
3158 gimple_stmt_iterator exit_gsi;
3159 tree vec_dest;
3160 tree new_temp = NULL_TREE, new_dest, new_name, new_scalar_dest;
3161 gimple epilog_stmt = NULL;
3162 enum tree_code code = gimple_assign_rhs_code (stmt);
3163 gimple exit_phi;
3164 tree bitsize, bitpos;
3165 tree adjustment_def = NULL;
3166 tree vec_initial_def = NULL;
3167 tree reduction_op, expr, def;
3168 tree orig_name, scalar_result;
3169 imm_use_iterator imm_iter, phi_imm_iter;
3170 use_operand_p use_p, phi_use_p;
3171 bool extract_scalar_result = false;
3172 gimple use_stmt, orig_stmt, reduction_phi = NULL;
3173 bool nested_in_vect_loop = false;
3174 VEC (gimple, heap) *new_phis = NULL;
3175 enum vect_def_type dt = vect_unknown_def_type;
3176 int j, i;
3177 VEC (tree, heap) *scalar_results = NULL;
3178 unsigned int group_size = 1, k, ratio;
3179 VEC (tree, heap) *vec_initial_defs = NULL;
3180 VEC (gimple, heap) *phis;
3181
3182 if (slp_node)
3183 group_size = VEC_length (gimple, SLP_TREE_SCALAR_STMTS (slp_node));
3184
3185 if (nested_in_vect_loop_p (loop, stmt))
3186 {
3187 outer_loop = loop;
3188 loop = loop->inner;
3189 nested_in_vect_loop = true;
3190 gcc_assert (!slp_node);
3191 }
3192
3193 switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
3194 {
3195 case GIMPLE_SINGLE_RHS:
3196 gcc_assert (TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt))
3197 == ternary_op);
3198 reduction_op = TREE_OPERAND (gimple_assign_rhs1 (stmt), reduc_index);
3199 break;
3200 case GIMPLE_UNARY_RHS:
3201 reduction_op = gimple_assign_rhs1 (stmt);
3202 break;
3203 case GIMPLE_BINARY_RHS:
3204 reduction_op = reduc_index ?
3205 gimple_assign_rhs2 (stmt) : gimple_assign_rhs1 (stmt);
3206 break;
3207 case GIMPLE_TERNARY_RHS:
3208 reduction_op = gimple_op (stmt, reduc_index + 1);
3209 break;
3210 default:
3211 gcc_unreachable ();
3212 }
3213
3214 vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op));
3215 gcc_assert (vectype);
3216 mode = TYPE_MODE (vectype);
3217
3218 /* 1. Create the reduction def-use cycle:
3219 Set the arguments of REDUCTION_PHIS, i.e., transform
3220
3221 loop:
3222 vec_def = phi <null, null> # REDUCTION_PHI
3223 VECT_DEF = vector_stmt # vectorized form of STMT
3224 ...
3225
3226 into:
3227
3228 loop:
3229 vec_def = phi <vec_init, VECT_DEF> # REDUCTION_PHI
3230 VECT_DEF = vector_stmt # vectorized form of STMT
3231 ...
3232
3233 (in case of SLP, do it for all the phis). */
3234
3235 /* Get the loop-entry arguments. */
3236 if (slp_node)
3237 vect_get_slp_defs (reduction_op, NULL_TREE, slp_node, &vec_initial_defs,
3238 NULL, reduc_index);
3239 else
3240 {
3241 vec_initial_defs = VEC_alloc (tree, heap, 1);
3242 /* For the case of reduction, vect_get_vec_def_for_operand returns
3243 the scalar def before the loop, that defines the initial value
3244 of the reduction variable. */
3245 vec_initial_def = vect_get_vec_def_for_operand (reduction_op, stmt,
3246 &adjustment_def);
3247 VEC_quick_push (tree, vec_initial_defs, vec_initial_def);
3248 }
3249
3250 /* Set phi nodes arguments. */
3251 FOR_EACH_VEC_ELT (gimple, reduction_phis, i, phi)
3252 {
3253 tree vec_init_def = VEC_index (tree, vec_initial_defs, i);
3254 tree def = VEC_index (tree, vect_defs, i);
3255 for (j = 0; j < ncopies; j++)
3256 {
3257 /* Set the loop-entry arg of the reduction-phi. */
3258 add_phi_arg (phi, vec_init_def, loop_preheader_edge (loop),
3259 UNKNOWN_LOCATION);
3260
3261 /* Set the loop-latch arg for the reduction-phi. */
3262 if (j > 0)
3263 def = vect_get_vec_def_for_stmt_copy (vect_unknown_def_type, def);
3264
3265 add_phi_arg (phi, def, loop_latch_edge (loop), UNKNOWN_LOCATION);
3266
3267 if (vect_print_dump_info (REPORT_DETAILS))
3268 {
3269 fprintf (vect_dump, "transform reduction: created def-use"
3270 " cycle: ");
3271 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
3272 fprintf (vect_dump, "\n");
3273 print_gimple_stmt (vect_dump, SSA_NAME_DEF_STMT (def), 0,
3274 TDF_SLIM);
3275 }
3276
3277 phi = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (phi));
3278 }
3279 }
3280
3281 VEC_free (tree, heap, vec_initial_defs);
3282
3283 /* 2. Create epilog code.
3284 The reduction epilog code operates across the elements of the vector
3285 of partial results computed by the vectorized loop.
3286 The reduction epilog code consists of:
3287
3288 step 1: compute the scalar result in a vector (v_out2)
3289 step 2: extract the scalar result (s_out3) from the vector (v_out2)
3290 step 3: adjust the scalar result (s_out3) if needed.
3291
3292 Step 1 can be accomplished using one the following three schemes:
3293 (scheme 1) using reduc_code, if available.
3294 (scheme 2) using whole-vector shifts, if available.
3295 (scheme 3) using a scalar loop. In this case steps 1+2 above are
3296 combined.
3297
3298 The overall epilog code looks like this:
3299
3300 s_out0 = phi <s_loop> # original EXIT_PHI
3301 v_out1 = phi <VECT_DEF> # NEW_EXIT_PHI
3302 v_out2 = reduce <v_out1> # step 1
3303 s_out3 = extract_field <v_out2, 0> # step 2
3304 s_out4 = adjust_result <s_out3> # step 3
3305
3306 (step 3 is optional, and steps 1 and 2 may be combined).
3307 Lastly, the uses of s_out0 are replaced by s_out4. */
3308
3309
3310 /* 2.1 Create new loop-exit-phis to preserve loop-closed form:
3311 v_out1 = phi <VECT_DEF>
3312 Store them in NEW_PHIS. */
3313
3314 exit_bb = single_exit (loop)->dest;
3315 prev_phi_info = NULL;
3316 new_phis = VEC_alloc (gimple, heap, VEC_length (tree, vect_defs));
3317 FOR_EACH_VEC_ELT (tree, vect_defs, i, def)
3318 {
3319 for (j = 0; j < ncopies; j++)
3320 {
3321 phi = create_phi_node (SSA_NAME_VAR (def), exit_bb);
3322 set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, loop_vinfo, NULL));
3323 if (j == 0)
3324 VEC_quick_push (gimple, new_phis, phi);
3325 else
3326 {
3327 def = vect_get_vec_def_for_stmt_copy (dt, def);
3328 STMT_VINFO_RELATED_STMT (prev_phi_info) = phi;
3329 }
3330
3331 SET_PHI_ARG_DEF (phi, single_exit (loop)->dest_idx, def);
3332 prev_phi_info = vinfo_for_stmt (phi);
3333 }
3334 }
3335
3336 /* The epilogue is created for the outer-loop, i.e., for the loop being
3337 vectorized. */
3338 if (double_reduc)
3339 {
3340 loop = outer_loop;
3341 exit_bb = single_exit (loop)->dest;
3342 }
3343
3344 exit_gsi = gsi_after_labels (exit_bb);
3345
3346 /* 2.2 Get the relevant tree-code to use in the epilog for schemes 2,3
3347 (i.e. when reduc_code is not available) and in the final adjustment
3348 code (if needed). Also get the original scalar reduction variable as
3349 defined in the loop. In case STMT is a "pattern-stmt" (i.e. - it
3350 represents a reduction pattern), the tree-code and scalar-def are
3351 taken from the original stmt that the pattern-stmt (STMT) replaces.
3352 Otherwise (it is a regular reduction) - the tree-code and scalar-def
3353 are taken from STMT. */
3354
3355 orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
3356 if (!orig_stmt)
3357 {
3358 /* Regular reduction */
3359 orig_stmt = stmt;
3360 }
3361 else
3362 {
3363 /* Reduction pattern */
3364 stmt_vec_info stmt_vinfo = vinfo_for_stmt (orig_stmt);
3365 gcc_assert (STMT_VINFO_IN_PATTERN_P (stmt_vinfo));
3366 gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt);
3367 }
3368
3369 code = gimple_assign_rhs_code (orig_stmt);
3370 /* For MINUS_EXPR the initial vector is [init_val,0,...,0], therefore,
3371 partial results are added and not subtracted. */
3372 if (code == MINUS_EXPR)
3373 code = PLUS_EXPR;
3374
3375 scalar_dest = gimple_assign_lhs (orig_stmt);
3376 scalar_type = TREE_TYPE (scalar_dest);
3377 scalar_results = VEC_alloc (tree, heap, group_size);
3378 new_scalar_dest = vect_create_destination_var (scalar_dest, NULL);
3379 bitsize = TYPE_SIZE (scalar_type);
3380
3381 /* In case this is a reduction in an inner-loop while vectorizing an outer
3382 loop - we don't need to extract a single scalar result at the end of the
3383 inner-loop (unless it is double reduction, i.e., the use of reduction is
3384 outside the outer-loop). The final vector of partial results will be used
3385 in the vectorized outer-loop, or reduced to a scalar result at the end of
3386 the outer-loop. */
3387 if (nested_in_vect_loop && !double_reduc)
3388 goto vect_finalize_reduction;
3389
3390 /* 2.3 Create the reduction code, using one of the three schemes described
3391 above. In SLP we simply need to extract all the elements from the
3392 vector (without reducing them), so we use scalar shifts. */
3393 if (reduc_code != ERROR_MARK && !slp_node)
3394 {
3395 tree tmp;
3396
3397 /*** Case 1: Create:
3398 v_out2 = reduc_expr <v_out1> */
3399
3400 if (vect_print_dump_info (REPORT_DETAILS))
3401 fprintf (vect_dump, "Reduce using direct vector reduction.");
3402
3403 vec_dest = vect_create_destination_var (scalar_dest, vectype);
3404 new_phi = VEC_index (gimple, new_phis, 0);
3405 tmp = build1 (reduc_code, vectype, PHI_RESULT (new_phi));
3406 epilog_stmt = gimple_build_assign (vec_dest, tmp);
3407 new_temp = make_ssa_name (vec_dest, epilog_stmt);
3408 gimple_assign_set_lhs (epilog_stmt, new_temp);
3409 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3410
3411 extract_scalar_result = true;
3412 }
3413 else
3414 {
3415 enum tree_code shift_code = ERROR_MARK;
3416 bool have_whole_vector_shift = true;
3417 int bit_offset;
3418 int element_bitsize = tree_low_cst (bitsize, 1);
3419 int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
3420 tree vec_temp;
3421
3422 if (optab_handler (vec_shr_optab, mode) != CODE_FOR_nothing)
3423 shift_code = VEC_RSHIFT_EXPR;
3424 else
3425 have_whole_vector_shift = false;
3426
3427 /* Regardless of whether we have a whole vector shift, if we're
3428 emulating the operation via tree-vect-generic, we don't want
3429 to use it. Only the first round of the reduction is likely
3430 to still be profitable via emulation. */
3431 /* ??? It might be better to emit a reduction tree code here, so that
3432 tree-vect-generic can expand the first round via bit tricks. */
3433 if (!VECTOR_MODE_P (mode))
3434 have_whole_vector_shift = false;
3435 else
3436 {
3437 optab optab = optab_for_tree_code (code, vectype, optab_default);
3438 if (optab_handler (optab, mode) == CODE_FOR_nothing)
3439 have_whole_vector_shift = false;
3440 }
3441
3442 if (have_whole_vector_shift && !slp_node)
3443 {
3444 /*** Case 2: Create:
3445 for (offset = VS/2; offset >= element_size; offset/=2)
3446 {
3447 Create: va' = vec_shift <va, offset>
3448 Create: va = vop <va, va'>
3449 } */
3450
3451 if (vect_print_dump_info (REPORT_DETAILS))
3452 fprintf (vect_dump, "Reduce using vector shifts");
3453
3454 vec_dest = vect_create_destination_var (scalar_dest, vectype);
3455 new_phi = VEC_index (gimple, new_phis, 0);
3456 new_temp = PHI_RESULT (new_phi);
3457 for (bit_offset = vec_size_in_bits/2;
3458 bit_offset >= element_bitsize;
3459 bit_offset /= 2)
3460 {
3461 tree bitpos = size_int (bit_offset);
3462
3463 epilog_stmt = gimple_build_assign_with_ops (shift_code,
3464 vec_dest, new_temp, bitpos);
3465 new_name = make_ssa_name (vec_dest, epilog_stmt);
3466 gimple_assign_set_lhs (epilog_stmt, new_name);
3467 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3468
3469 epilog_stmt = gimple_build_assign_with_ops (code, vec_dest,
3470 new_name, new_temp);
3471 new_temp = make_ssa_name (vec_dest, epilog_stmt);
3472 gimple_assign_set_lhs (epilog_stmt, new_temp);
3473 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3474 }
3475
3476 extract_scalar_result = true;
3477 }
3478 else
3479 {
3480 tree rhs;
3481
3482 /*** Case 3: Create:
3483 s = extract_field <v_out2, 0>
3484 for (offset = element_size;
3485 offset < vector_size;
3486 offset += element_size;)
3487 {
3488 Create: s' = extract_field <v_out2, offset>
3489 Create: s = op <s, s'> // For non SLP cases
3490 } */
3491
3492 if (vect_print_dump_info (REPORT_DETAILS))
3493 fprintf (vect_dump, "Reduce using scalar code. ");
3494
3495 vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
3496 FOR_EACH_VEC_ELT (gimple, new_phis, i, new_phi)
3497 {
3498 vec_temp = PHI_RESULT (new_phi);
3499 rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
3500 bitsize_zero_node);
3501 epilog_stmt = gimple_build_assign (new_scalar_dest, rhs);
3502 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
3503 gimple_assign_set_lhs (epilog_stmt, new_temp);
3504 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3505
3506 /* In SLP we don't need to apply reduction operation, so we just
3507 collect s' values in SCALAR_RESULTS. */
3508 if (slp_node)
3509 VEC_safe_push (tree, heap, scalar_results, new_temp);
3510
3511 for (bit_offset = element_bitsize;
3512 bit_offset < vec_size_in_bits;
3513 bit_offset += element_bitsize)
3514 {
3515 tree bitpos = bitsize_int (bit_offset);
3516 tree rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp,
3517 bitsize, bitpos);
3518
3519 epilog_stmt = gimple_build_assign (new_scalar_dest, rhs);
3520 new_name = make_ssa_name (new_scalar_dest, epilog_stmt);
3521 gimple_assign_set_lhs (epilog_stmt, new_name);
3522 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3523
3524 if (slp_node)
3525 {
3526 /* In SLP we don't need to apply reduction operation, so
3527 we just collect s' values in SCALAR_RESULTS. */
3528 new_temp = new_name;
3529 VEC_safe_push (tree, heap, scalar_results, new_name);
3530 }
3531 else
3532 {
3533 epilog_stmt = gimple_build_assign_with_ops (code,
3534 new_scalar_dest, new_name, new_temp);
3535 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
3536 gimple_assign_set_lhs (epilog_stmt, new_temp);
3537 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3538 }
3539 }
3540 }
3541
3542 /* The only case where we need to reduce scalar results in SLP, is
3543 unrolling. If the size of SCALAR_RESULTS is greater than
3544 GROUP_SIZE, we reduce them combining elements modulo
3545 GROUP_SIZE. */
3546 if (slp_node)
3547 {
3548 tree res, first_res, new_res;
3549 gimple new_stmt;
3550
3551 /* Reduce multiple scalar results in case of SLP unrolling. */
3552 for (j = group_size; VEC_iterate (tree, scalar_results, j, res);
3553 j++)
3554 {
3555 first_res = VEC_index (tree, scalar_results, j % group_size);
3556 new_stmt = gimple_build_assign_with_ops (code,
3557 new_scalar_dest, first_res, res);
3558 new_res = make_ssa_name (new_scalar_dest, new_stmt);
3559 gimple_assign_set_lhs (new_stmt, new_res);
3560 gsi_insert_before (&exit_gsi, new_stmt, GSI_SAME_STMT);
3561 VEC_replace (tree, scalar_results, j % group_size, new_res);
3562 }
3563 }
3564 else
3565 /* Not SLP - we have one scalar to keep in SCALAR_RESULTS. */
3566 VEC_safe_push (tree, heap, scalar_results, new_temp);
3567
3568 extract_scalar_result = false;
3569 }
3570 }
3571
3572 /* 2.4 Extract the final scalar result. Create:
3573 s_out3 = extract_field <v_out2, bitpos> */
3574
3575 if (extract_scalar_result)
3576 {
3577 tree rhs;
3578
3579 if (vect_print_dump_info (REPORT_DETAILS))
3580 fprintf (vect_dump, "extract scalar result");
3581
3582 if (BYTES_BIG_ENDIAN)
3583 bitpos = size_binop (MULT_EXPR,
3584 bitsize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1),
3585 TYPE_SIZE (scalar_type));
3586 else
3587 bitpos = bitsize_zero_node;
3588
3589 rhs = build3 (BIT_FIELD_REF, scalar_type, new_temp, bitsize, bitpos);
3590 epilog_stmt = gimple_build_assign (new_scalar_dest, rhs);
3591 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
3592 gimple_assign_set_lhs (epilog_stmt, new_temp);
3593 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3594 VEC_safe_push (tree, heap, scalar_results, new_temp);
3595 }
3596
3597 vect_finalize_reduction:
3598
3599 if (double_reduc)
3600 loop = loop->inner;
3601
3602 /* 2.5 Adjust the final result by the initial value of the reduction
3603 variable. (When such adjustment is not needed, then
3604 'adjustment_def' is zero). For example, if code is PLUS we create:
3605 new_temp = loop_exit_def + adjustment_def */
3606
3607 if (adjustment_def)
3608 {
3609 gcc_assert (!slp_node);
3610 if (nested_in_vect_loop)
3611 {
3612 new_phi = VEC_index (gimple, new_phis, 0);
3613 gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) == VECTOR_TYPE);
3614 expr = build2 (code, vectype, PHI_RESULT (new_phi), adjustment_def);
3615 new_dest = vect_create_destination_var (scalar_dest, vectype);
3616 }
3617 else
3618 {
3619 new_temp = VEC_index (tree, scalar_results, 0);
3620 gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) != VECTOR_TYPE);
3621 expr = build2 (code, scalar_type, new_temp, adjustment_def);
3622 new_dest = vect_create_destination_var (scalar_dest, scalar_type);
3623 }
3624
3625 epilog_stmt = gimple_build_assign (new_dest, expr);
3626 new_temp = make_ssa_name (new_dest, epilog_stmt);
3627 gimple_assign_set_lhs (epilog_stmt, new_temp);
3628 SSA_NAME_DEF_STMT (new_temp) = epilog_stmt;
3629 gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
3630 if (nested_in_vect_loop)
3631 {
3632 set_vinfo_for_stmt (epilog_stmt,
3633 new_stmt_vec_info (epilog_stmt, loop_vinfo,
3634 NULL));
3635 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (epilog_stmt)) =
3636 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (new_phi));
3637
3638 if (!double_reduc)
3639 VEC_quick_push (tree, scalar_results, new_temp);
3640 else
3641 VEC_replace (tree, scalar_results, 0, new_temp);
3642 }
3643 else
3644 VEC_replace (tree, scalar_results, 0, new_temp);
3645
3646 VEC_replace (gimple, new_phis, 0, epilog_stmt);
3647 }
3648
3649 /* 2.6 Handle the loop-exit phis. Replace the uses of scalar loop-exit
3650 phis with new adjusted scalar results, i.e., replace use <s_out0>
3651 with use <s_out4>.
3652
3653 Transform:
3654 loop_exit:
3655 s_out0 = phi <s_loop> # (scalar) EXIT_PHI
3656 v_out1 = phi <VECT_DEF> # NEW_EXIT_PHI
3657 v_out2 = reduce <v_out1>
3658 s_out3 = extract_field <v_out2, 0>
3659 s_out4 = adjust_result <s_out3>
3660 use <s_out0>
3661 use <s_out0>
3662
3663 into:
3664
3665 loop_exit:
3666 s_out0 = phi <s_loop> # (scalar) EXIT_PHI
3667 v_out1 = phi <VECT_DEF> # NEW_EXIT_PHI
3668 v_out2 = reduce <v_out1>
3669 s_out3 = extract_field <v_out2, 0>
3670 s_out4 = adjust_result <s_out3>
3671 use <s_out4>
3672 use <s_out4> */
3673
3674 /* In SLP we may have several statements in NEW_PHIS and REDUCTION_PHIS (in
3675 case that GROUP_SIZE is greater than vectorization factor). Therefore, we
3676 need to match SCALAR_RESULTS with corresponding statements. The first
3677 (GROUP_SIZE / number of new vector stmts) scalar results correspond to
3678 the first vector stmt, etc.
3679 (RATIO is equal to (GROUP_SIZE / number of new vector stmts)). */
3680 if (group_size > VEC_length (gimple, new_phis))
3681 {
3682 ratio = group_size / VEC_length (gimple, new_phis);
3683 gcc_assert (!(group_size % VEC_length (gimple, new_phis)));
3684 }
3685 else
3686 ratio = 1;
3687
3688 for (k = 0; k < group_size; k++)
3689 {
3690 if (k % ratio == 0)
3691 {
3692 epilog_stmt = VEC_index (gimple, new_phis, k / ratio);
3693 reduction_phi = VEC_index (gimple, reduction_phis, k / ratio);
3694 }
3695
3696 if (slp_node)
3697 {
3698 gimple current_stmt = VEC_index (gimple,
3699 SLP_TREE_SCALAR_STMTS (slp_node), k);
3700
3701 orig_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (current_stmt));
3702 /* SLP statements can't participate in patterns. */
3703 gcc_assert (!orig_stmt);
3704 scalar_dest = gimple_assign_lhs (current_stmt);
3705 }
3706
3707 phis = VEC_alloc (gimple, heap, 3);
3708 /* Find the loop-closed-use at the loop exit of the original scalar
3709 result. (The reduction result is expected to have two immediate uses -
3710 one at the latch block, and one at the loop exit). */
3711 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
3712 if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
3713 VEC_safe_push (gimple, heap, phis, USE_STMT (use_p));
3714
3715 /* We expect to have found an exit_phi because of loop-closed-ssa
3716 form. */
3717 gcc_assert (!VEC_empty (gimple, phis));
3718
3719 FOR_EACH_VEC_ELT (gimple, phis, i, exit_phi)
3720 {
3721 if (outer_loop)
3722 {
3723 stmt_vec_info exit_phi_vinfo = vinfo_for_stmt (exit_phi);
3724 gimple vect_phi;
3725
3726 /* FORNOW. Currently not supporting the case that an inner-loop
3727 reduction is not used in the outer-loop (but only outside the
3728 outer-loop), unless it is double reduction. */
3729 gcc_assert ((STMT_VINFO_RELEVANT_P (exit_phi_vinfo)
3730 && !STMT_VINFO_LIVE_P (exit_phi_vinfo))
3731 || double_reduc);
3732
3733 STMT_VINFO_VEC_STMT (exit_phi_vinfo) = epilog_stmt;
3734 if (!double_reduc
3735 || STMT_VINFO_DEF_TYPE (exit_phi_vinfo)
3736 != vect_double_reduction_def)
3737 continue;
3738
3739 /* Handle double reduction:
3740
3741 stmt1: s1 = phi <s0, s2> - double reduction phi (outer loop)
3742 stmt2: s3 = phi <s1, s4> - (regular) reduc phi (inner loop)
3743 stmt3: s4 = use (s3) - (regular) reduc stmt (inner loop)
3744 stmt4: s2 = phi <s4> - double reduction stmt (outer loop)
3745
3746 At that point the regular reduction (stmt2 and stmt3) is
3747 already vectorized, as well as the exit phi node, stmt4.
3748 Here we vectorize the phi node of double reduction, stmt1, and
3749 update all relevant statements. */
3750
3751 /* Go through all the uses of s2 to find double reduction phi
3752 node, i.e., stmt1 above. */
3753 orig_name = PHI_RESULT (exit_phi);
3754 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name)
3755 {
3756 stmt_vec_info use_stmt_vinfo = vinfo_for_stmt (use_stmt);
3757 stmt_vec_info new_phi_vinfo;
3758 tree vect_phi_init, preheader_arg, vect_phi_res, init_def;
3759 basic_block bb = gimple_bb (use_stmt);
3760 gimple use;
3761
3762 /* Check that USE_STMT is really double reduction phi
3763 node. */
3764 if (gimple_code (use_stmt) != GIMPLE_PHI
3765 || gimple_phi_num_args (use_stmt) != 2
3766 || !use_stmt_vinfo
3767 || STMT_VINFO_DEF_TYPE (use_stmt_vinfo)
3768 != vect_double_reduction_def
3769 || bb->loop_father != outer_loop)
3770 continue;
3771
3772 /* Create vector phi node for double reduction:
3773 vs1 = phi <vs0, vs2>
3774 vs1 was created previously in this function by a call to
3775 vect_get_vec_def_for_operand and is stored in
3776 vec_initial_def;
3777 vs2 is defined by EPILOG_STMT, the vectorized EXIT_PHI;
3778 vs0 is created here. */
3779
3780 /* Create vector phi node. */
3781 vect_phi = create_phi_node (vec_initial_def, bb);
3782 new_phi_vinfo = new_stmt_vec_info (vect_phi,
3783 loop_vec_info_for_loop (outer_loop), NULL);
3784 set_vinfo_for_stmt (vect_phi, new_phi_vinfo);
3785
3786 /* Create vs0 - initial def of the double reduction phi. */
3787 preheader_arg = PHI_ARG_DEF_FROM_EDGE (use_stmt,
3788 loop_preheader_edge (outer_loop));
3789 init_def = get_initial_def_for_reduction (stmt,
3790 preheader_arg, NULL);
3791 vect_phi_init = vect_init_vector (use_stmt, init_def,
3792 vectype, NULL);
3793
3794 /* Update phi node arguments with vs0 and vs2. */
3795 add_phi_arg (vect_phi, vect_phi_init,
3796 loop_preheader_edge (outer_loop),
3797 UNKNOWN_LOCATION);
3798 add_phi_arg (vect_phi, PHI_RESULT (epilog_stmt),
3799 loop_latch_edge (outer_loop), UNKNOWN_LOCATION);
3800 if (vect_print_dump_info (REPORT_DETAILS))
3801 {
3802 fprintf (vect_dump, "created double reduction phi "
3803 "node: ");
3804 print_gimple_stmt (vect_dump, vect_phi, 0, TDF_SLIM);
3805 }
3806
3807 vect_phi_res = PHI_RESULT (vect_phi);
3808
3809 /* Replace the use, i.e., set the correct vs1 in the regular
3810 reduction phi node. FORNOW, NCOPIES is always 1, so the
3811 loop is redundant. */
3812 use = reduction_phi;
3813 for (j = 0; j < ncopies; j++)
3814 {
3815 edge pr_edge = loop_preheader_edge (loop);
3816 SET_PHI_ARG_DEF (use, pr_edge->dest_idx, vect_phi_res);
3817 use = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use));
3818 }
3819 }
3820 }
3821 }
3822
3823 VEC_free (gimple, heap, phis);
3824 if (nested_in_vect_loop)
3825 {
3826 if (double_reduc)
3827 loop = outer_loop;
3828 else
3829 continue;
3830 }
3831
3832 phis = VEC_alloc (gimple, heap, 3);
3833 /* Find the loop-closed-use at the loop exit of the original scalar
3834 result. (The reduction result is expected to have two immediate uses,
3835 one at the latch block, and one at the loop exit). For double
3836 reductions we are looking for exit phis of the outer loop. */
3837 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
3838 {
3839 if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
3840 VEC_safe_push (gimple, heap, phis, USE_STMT (use_p));
3841 else
3842 {
3843 if (double_reduc && gimple_code (USE_STMT (use_p)) == GIMPLE_PHI)
3844 {
3845 tree phi_res = PHI_RESULT (USE_STMT (use_p));
3846
3847 FOR_EACH_IMM_USE_FAST (phi_use_p, phi_imm_iter, phi_res)
3848 {
3849 if (!flow_bb_inside_loop_p (loop,
3850 gimple_bb (USE_STMT (phi_use_p))))
3851 VEC_safe_push (gimple, heap, phis,
3852 USE_STMT (phi_use_p));
3853 }
3854 }
3855 }
3856 }
3857
3858 FOR_EACH_VEC_ELT (gimple, phis, i, exit_phi)
3859 {
3860 /* Replace the uses: */
3861 orig_name = PHI_RESULT (exit_phi);
3862 scalar_result = VEC_index (tree, scalar_results, k);
3863 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name)
3864 FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
3865 SET_USE (use_p, scalar_result);
3866 }
3867
3868 VEC_free (gimple, heap, phis);
3869 }
3870
3871 VEC_free (tree, heap, scalar_results);
3872 VEC_free (gimple, heap, new_phis);
3873 }
3874
3875
3876 /* Function vectorizable_reduction.
3877
3878 Check if STMT performs a reduction operation that can be vectorized.
3879 If VEC_STMT is also passed, vectorize the STMT: create a vectorized
3880 stmt to replace it, put it in VEC_STMT, and insert it at GSI.
3881 Return FALSE if not a vectorizable STMT, TRUE otherwise.
3882
3883 This function also handles reduction idioms (patterns) that have been
3884 recognized in advance during vect_pattern_recog. In this case, STMT may be
3885 of this form:
3886 X = pattern_expr (arg0, arg1, ..., X)
3887 and it's STMT_VINFO_RELATED_STMT points to the last stmt in the original
3888 sequence that had been detected and replaced by the pattern-stmt (STMT).
3889
3890 In some cases of reduction patterns, the type of the reduction variable X is
3891 different than the type of the other arguments of STMT.
3892 In such cases, the vectype that is used when transforming STMT into a vector
3893 stmt is different than the vectype that is used to determine the
3894 vectorization factor, because it consists of a different number of elements
3895 than the actual number of elements that are being operated upon in parallel.
3896
3897 For example, consider an accumulation of shorts into an int accumulator.
3898 On some targets it's possible to vectorize this pattern operating on 8
3899 shorts at a time (hence, the vectype for purposes of determining the
3900 vectorization factor should be V8HI); on the other hand, the vectype that
3901 is used to create the vector form is actually V4SI (the type of the result).
3902
3903 Upon entry to this function, STMT_VINFO_VECTYPE records the vectype that
3904 indicates what is the actual level of parallelism (V8HI in the example), so
3905 that the right vectorization factor would be derived. This vectype
3906 corresponds to the type of arguments to the reduction stmt, and should *NOT*
3907 be used to create the vectorized stmt. The right vectype for the vectorized
3908 stmt is obtained from the type of the result X:
3909 get_vectype_for_scalar_type (TREE_TYPE (X))
3910
3911 This means that, contrary to "regular" reductions (or "regular" stmts in
3912 general), the following equation:
3913 STMT_VINFO_VECTYPE == get_vectype_for_scalar_type (TREE_TYPE (X))
3914 does *NOT* necessarily hold for reduction patterns. */
3915
3916 bool
3917 vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
3918 gimple *vec_stmt, slp_tree slp_node)
3919 {
3920 tree vec_dest;
3921 tree scalar_dest;
3922 tree loop_vec_def0 = NULL_TREE, loop_vec_def1 = NULL_TREE;
3923 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3924 tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
3925 tree vectype_in = NULL_TREE;
3926 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3927 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
3928 enum tree_code code, orig_code, epilog_reduc_code;
3929 enum machine_mode vec_mode;
3930 int op_type;
3931 optab optab, reduc_optab;
3932 tree new_temp = NULL_TREE;
3933 tree def;
3934 gimple def_stmt;
3935 enum vect_def_type dt;
3936 gimple new_phi = NULL;
3937 tree scalar_type;
3938 bool is_simple_use;
3939 gimple orig_stmt;
3940 stmt_vec_info orig_stmt_info;
3941 tree expr = NULL_TREE;
3942 int i;
3943 int ncopies;
3944 int epilog_copies;
3945 stmt_vec_info prev_stmt_info, prev_phi_info;
3946 bool single_defuse_cycle = false;
3947 tree reduc_def = NULL_TREE;
3948 gimple new_stmt = NULL;
3949 int j;
3950 tree ops[3];
3951 bool nested_cycle = false, found_nested_cycle_def = false;
3952 gimple reduc_def_stmt = NULL;
3953 /* The default is that the reduction variable is the last in statement. */
3954 int reduc_index = 2;
3955 bool double_reduc = false, dummy;
3956 basic_block def_bb;
3957 struct loop * def_stmt_loop, *outer_loop = NULL;
3958 tree def_arg;
3959 gimple def_arg_stmt;
3960 VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL, *vect_defs = NULL;
3961 VEC (gimple, heap) *phis = NULL;
3962 int vec_num;
3963 tree def0, def1, tem;
3964
3965 if (nested_in_vect_loop_p (loop, stmt))
3966 {
3967 outer_loop = loop;
3968 loop = loop->inner;
3969 nested_cycle = true;
3970 }
3971
3972 /* 1. Is vectorizable reduction? */
3973 /* Not supportable if the reduction variable is used in the loop. */
3974 if (STMT_VINFO_RELEVANT (stmt_info) > vect_used_in_outer)
3975 return false;
3976
3977 /* Reductions that are not used even in an enclosing outer-loop,
3978 are expected to be "live" (used out of the loop). */
3979 if (STMT_VINFO_RELEVANT (stmt_info) == vect_unused_in_scope
3980 && !STMT_VINFO_LIVE_P (stmt_info))
3981 return false;
3982
3983 /* Make sure it was already recognized as a reduction computation. */
3984 if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def
3985 && STMT_VINFO_DEF_TYPE (stmt_info) != vect_nested_cycle)
3986 return false;
3987
3988 /* 2. Has this been recognized as a reduction pattern?
3989
3990 Check if STMT represents a pattern that has been recognized
3991 in earlier analysis stages. For stmts that represent a pattern,
3992 the STMT_VINFO_RELATED_STMT field records the last stmt in
3993 the original sequence that constitutes the pattern. */
3994
3995 orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
3996 if (orig_stmt)
3997 {
3998 orig_stmt_info = vinfo_for_stmt (orig_stmt);
3999 gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info) == stmt);
4000 gcc_assert (STMT_VINFO_IN_PATTERN_P (orig_stmt_info));
4001 gcc_assert (!STMT_VINFO_IN_PATTERN_P (stmt_info));
4002 }
4003
4004 /* 3. Check the operands of the operation. The first operands are defined
4005 inside the loop body. The last operand is the reduction variable,
4006 which is defined by the loop-header-phi. */
4007
4008 gcc_assert (is_gimple_assign (stmt));
4009
4010 /* Flatten RHS. */
4011 switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
4012 {
4013 case GIMPLE_SINGLE_RHS:
4014 op_type = TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt));
4015 if (op_type == ternary_op)
4016 {
4017 tree rhs = gimple_assign_rhs1 (stmt);
4018 ops[0] = TREE_OPERAND (rhs, 0);
4019 ops[1] = TREE_OPERAND (rhs, 1);
4020 ops[2] = TREE_OPERAND (rhs, 2);
4021 code = TREE_CODE (rhs);
4022 }
4023 else
4024 return false;
4025 break;
4026
4027 case GIMPLE_BINARY_RHS:
4028 code = gimple_assign_rhs_code (stmt);
4029 op_type = TREE_CODE_LENGTH (code);
4030 gcc_assert (op_type == binary_op);
4031 ops[0] = gimple_assign_rhs1 (stmt);
4032 ops[1] = gimple_assign_rhs2 (stmt);
4033 break;
4034
4035 case GIMPLE_TERNARY_RHS:
4036 code = gimple_assign_rhs_code (stmt);
4037 op_type = TREE_CODE_LENGTH (code);
4038 gcc_assert (op_type == ternary_op);
4039 ops[0] = gimple_assign_rhs1 (stmt);
4040 ops[1] = gimple_assign_rhs2 (stmt);
4041 ops[2] = gimple_assign_rhs3 (stmt);
4042 break;
4043
4044 case GIMPLE_UNARY_RHS:
4045 return false;
4046
4047 default:
4048 gcc_unreachable ();
4049 }
4050
4051 scalar_dest = gimple_assign_lhs (stmt);
4052 scalar_type = TREE_TYPE (scalar_dest);
4053 if (!POINTER_TYPE_P (scalar_type) && !INTEGRAL_TYPE_P (scalar_type)
4054 && !SCALAR_FLOAT_TYPE_P (scalar_type))
4055 return false;
4056
4057 /* All uses but the last are expected to be defined in the loop.
4058 The last use is the reduction variable. In case of nested cycle this
4059 assumption is not true: we use reduc_index to record the index of the
4060 reduction variable. */
4061 for (i = 0; i < op_type-1; i++)
4062 {
4063 /* The condition of COND_EXPR is checked in vectorizable_condition(). */
4064 if (i == 0 && code == COND_EXPR)
4065 continue;
4066
4067 is_simple_use = vect_is_simple_use_1 (ops[i], loop_vinfo, NULL,
4068 &def_stmt, &def, &dt, &tem);
4069 if (!vectype_in)
4070 vectype_in = tem;
4071 gcc_assert (is_simple_use);
4072 if (dt != vect_internal_def
4073 && dt != vect_external_def
4074 && dt != vect_constant_def
4075 && dt != vect_induction_def
4076 && !(dt == vect_nested_cycle && nested_cycle))
4077 return false;
4078
4079 if (dt == vect_nested_cycle)
4080 {
4081 found_nested_cycle_def = true;
4082 reduc_def_stmt = def_stmt;
4083 reduc_index = i;
4084 }
4085 }
4086
4087 is_simple_use = vect_is_simple_use_1 (ops[i], loop_vinfo, NULL, &def_stmt,
4088 &def, &dt, &tem);
4089 if (!vectype_in)
4090 vectype_in = tem;
4091 gcc_assert (is_simple_use);
4092 gcc_assert (dt == vect_reduction_def
4093 || dt == vect_nested_cycle
4094 || ((dt == vect_internal_def || dt == vect_external_def
4095 || dt == vect_constant_def || dt == vect_induction_def)
4096 && nested_cycle && found_nested_cycle_def));
4097 if (!found_nested_cycle_def)
4098 reduc_def_stmt = def_stmt;
4099
4100 gcc_assert (gimple_code (reduc_def_stmt) == GIMPLE_PHI);
4101 if (orig_stmt)
4102 gcc_assert (orig_stmt == vect_is_simple_reduction (loop_vinfo,
4103 reduc_def_stmt,
4104 !nested_cycle,
4105 &dummy));
4106 else
4107 gcc_assert (stmt == vect_is_simple_reduction (loop_vinfo, reduc_def_stmt,
4108 !nested_cycle, &dummy));
4109
4110 if (STMT_VINFO_LIVE_P (vinfo_for_stmt (reduc_def_stmt)))
4111 return false;
4112
4113 if (slp_node)
4114 ncopies = 1;
4115 else
4116 ncopies = (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
4117 / TYPE_VECTOR_SUBPARTS (vectype_in));
4118
4119 gcc_assert (ncopies >= 1);
4120
4121 vec_mode = TYPE_MODE (vectype_in);
4122
4123 if (code == COND_EXPR)
4124 {
4125 if (!vectorizable_condition (stmt, gsi, NULL, ops[reduc_index], 0))
4126 {
4127 if (vect_print_dump_info (REPORT_DETAILS))
4128 fprintf (vect_dump, "unsupported condition in reduction");
4129
4130 return false;
4131 }
4132 }
4133 else
4134 {
4135 /* 4. Supportable by target? */
4136
4137 /* 4.1. check support for the operation in the loop */
4138 optab = optab_for_tree_code (code, vectype_in, optab_default);
4139 if (!optab)
4140 {
4141 if (vect_print_dump_info (REPORT_DETAILS))
4142 fprintf (vect_dump, "no optab.");
4143
4144 return false;
4145 }
4146
4147 if (optab_handler (optab, vec_mode) == CODE_FOR_nothing)
4148 {
4149 if (vect_print_dump_info (REPORT_DETAILS))
4150 fprintf (vect_dump, "op not supported by target.");
4151
4152 if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
4153 || LOOP_VINFO_VECT_FACTOR (loop_vinfo)
4154 < vect_min_worthwhile_factor (code))
4155 return false;
4156
4157 if (vect_print_dump_info (REPORT_DETAILS))
4158 fprintf (vect_dump, "proceeding using word mode.");
4159 }
4160
4161 /* Worthwhile without SIMD support? */
4162 if (!VECTOR_MODE_P (TYPE_MODE (vectype_in))
4163 && LOOP_VINFO_VECT_FACTOR (loop_vinfo)
4164 < vect_min_worthwhile_factor (code))
4165 {
4166 if (vect_print_dump_info (REPORT_DETAILS))
4167 fprintf (vect_dump, "not worthwhile without SIMD support.");
4168
4169 return false;
4170 }
4171 }
4172
4173 /* 4.2. Check support for the epilog operation.
4174
4175 If STMT represents a reduction pattern, then the type of the
4176 reduction variable may be different than the type of the rest
4177 of the arguments. For example, consider the case of accumulation
4178 of shorts into an int accumulator; The original code:
4179 S1: int_a = (int) short_a;
4180 orig_stmt-> S2: int_acc = plus <int_a ,int_acc>;
4181
4182 was replaced with:
4183 STMT: int_acc = widen_sum <short_a, int_acc>
4184
4185 This means that:
4186 1. The tree-code that is used to create the vector operation in the
4187 epilog code (that reduces the partial results) is not the
4188 tree-code of STMT, but is rather the tree-code of the original
4189 stmt from the pattern that STMT is replacing. I.e, in the example
4190 above we want to use 'widen_sum' in the loop, but 'plus' in the
4191 epilog.
4192 2. The type (mode) we use to check available target support
4193 for the vector operation to be created in the *epilog*, is
4194 determined by the type of the reduction variable (in the example
4195 above we'd check this: optab_handler (plus_optab, vect_int_mode])).
4196 However the type (mode) we use to check available target support
4197 for the vector operation to be created *inside the loop*, is
4198 determined by the type of the other arguments to STMT (in the
4199 example we'd check this: optab_handler (widen_sum_optab,
4200 vect_short_mode)).
4201
4202 This is contrary to "regular" reductions, in which the types of all
4203 the arguments are the same as the type of the reduction variable.
4204 For "regular" reductions we can therefore use the same vector type
4205 (and also the same tree-code) when generating the epilog code and
4206 when generating the code inside the loop. */
4207
4208 if (orig_stmt)
4209 {
4210 /* This is a reduction pattern: get the vectype from the type of the
4211 reduction variable, and get the tree-code from orig_stmt. */
4212 orig_code = gimple_assign_rhs_code (orig_stmt);
4213 gcc_assert (vectype_out);
4214 vec_mode = TYPE_MODE (vectype_out);
4215 }
4216 else
4217 {
4218 /* Regular reduction: use the same vectype and tree-code as used for
4219 the vector code inside the loop can be used for the epilog code. */
4220 orig_code = code;
4221 }
4222
4223 if (nested_cycle)
4224 {
4225 def_bb = gimple_bb (reduc_def_stmt);
4226 def_stmt_loop = def_bb->loop_father;
4227 def_arg = PHI_ARG_DEF_FROM_EDGE (reduc_def_stmt,
4228 loop_preheader_edge (def_stmt_loop));
4229 if (TREE_CODE (def_arg) == SSA_NAME
4230 && (def_arg_stmt = SSA_NAME_DEF_STMT (def_arg))
4231 && gimple_code (def_arg_stmt) == GIMPLE_PHI
4232 && flow_bb_inside_loop_p (outer_loop, gimple_bb (def_arg_stmt))
4233 && vinfo_for_stmt (def_arg_stmt)
4234 && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_arg_stmt))
4235 == vect_double_reduction_def)
4236 double_reduc = true;
4237 }
4238
4239 epilog_reduc_code = ERROR_MARK;
4240 if (reduction_code_for_scalar_code (orig_code, &epilog_reduc_code))
4241 {
4242 reduc_optab = optab_for_tree_code (epilog_reduc_code, vectype_out,
4243 optab_default);
4244 if (!reduc_optab)
4245 {
4246 if (vect_print_dump_info (REPORT_DETAILS))
4247 fprintf (vect_dump, "no optab for reduction.");
4248
4249 epilog_reduc_code = ERROR_MARK;
4250 }
4251
4252 if (reduc_optab
4253 && optab_handler (reduc_optab, vec_mode) == CODE_FOR_nothing)
4254 {
4255 if (vect_print_dump_info (REPORT_DETAILS))
4256 fprintf (vect_dump, "reduc op not supported by target.");
4257
4258 epilog_reduc_code = ERROR_MARK;
4259 }
4260 }
4261 else
4262 {
4263 if (!nested_cycle || double_reduc)
4264 {
4265 if (vect_print_dump_info (REPORT_DETAILS))
4266 fprintf (vect_dump, "no reduc code for scalar code.");
4267
4268 return false;
4269 }
4270 }
4271
4272 if (double_reduc && ncopies > 1)
4273 {
4274 if (vect_print_dump_info (REPORT_DETAILS))
4275 fprintf (vect_dump, "multiple types in double reduction");
4276
4277 return false;
4278 }
4279
4280 if (!vec_stmt) /* transformation not required. */
4281 {
4282 STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
4283 if (!vect_model_reduction_cost (stmt_info, epilog_reduc_code, ncopies))
4284 return false;
4285 return true;
4286 }
4287
4288 /** Transform. **/
4289
4290 if (vect_print_dump_info (REPORT_DETAILS))
4291 fprintf (vect_dump, "transform reduction.");
4292
4293 /* FORNOW: Multiple types are not supported for condition. */
4294 if (code == COND_EXPR)
4295 gcc_assert (ncopies == 1);
4296
4297 /* Create the destination vector */
4298 vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
4299
4300 /* In case the vectorization factor (VF) is bigger than the number
4301 of elements that we can fit in a vectype (nunits), we have to generate
4302 more than one vector stmt - i.e - we need to "unroll" the
4303 vector stmt by a factor VF/nunits. For more details see documentation
4304 in vectorizable_operation. */
4305
4306 /* If the reduction is used in an outer loop we need to generate
4307 VF intermediate results, like so (e.g. for ncopies=2):
4308 r0 = phi (init, r0)
4309 r1 = phi (init, r1)
4310 r0 = x0 + r0;
4311 r1 = x1 + r1;
4312 (i.e. we generate VF results in 2 registers).
4313 In this case we have a separate def-use cycle for each copy, and therefore
4314 for each copy we get the vector def for the reduction variable from the
4315 respective phi node created for this copy.
4316
4317 Otherwise (the reduction is unused in the loop nest), we can combine
4318 together intermediate results, like so (e.g. for ncopies=2):
4319 r = phi (init, r)
4320 r = x0 + r;
4321 r = x1 + r;
4322 (i.e. we generate VF/2 results in a single register).
4323 In this case for each copy we get the vector def for the reduction variable
4324 from the vectorized reduction operation generated in the previous iteration.
4325 */
4326
4327 if (STMT_VINFO_RELEVANT (stmt_info) == vect_unused_in_scope)
4328 {
4329 single_defuse_cycle = true;
4330 epilog_copies = 1;
4331 }
4332 else
4333 epilog_copies = ncopies;
4334
4335 prev_stmt_info = NULL;
4336 prev_phi_info = NULL;
4337 if (slp_node)
4338 {
4339 vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
4340 gcc_assert (TYPE_VECTOR_SUBPARTS (vectype_out)
4341 == TYPE_VECTOR_SUBPARTS (vectype_in));
4342 }
4343 else
4344 {
4345 vec_num = 1;
4346 vec_oprnds0 = VEC_alloc (tree, heap, 1);
4347 if (op_type == ternary_op)
4348 vec_oprnds1 = VEC_alloc (tree, heap, 1);
4349 }
4350
4351 phis = VEC_alloc (gimple, heap, vec_num);
4352 vect_defs = VEC_alloc (tree, heap, vec_num);
4353 if (!slp_node)
4354 VEC_quick_push (tree, vect_defs, NULL_TREE);
4355
4356 for (j = 0; j < ncopies; j++)
4357 {
4358 if (j == 0 || !single_defuse_cycle)
4359 {
4360 for (i = 0; i < vec_num; i++)
4361 {
4362 /* Create the reduction-phi that defines the reduction
4363 operand. */
4364 new_phi = create_phi_node (vec_dest, loop->header);
4365 set_vinfo_for_stmt (new_phi,
4366 new_stmt_vec_info (new_phi, loop_vinfo,
4367 NULL));
4368 if (j == 0 || slp_node)
4369 VEC_quick_push (gimple, phis, new_phi);
4370 }
4371 }
4372
4373 if (code == COND_EXPR)
4374 {
4375 gcc_assert (!slp_node);
4376 vectorizable_condition (stmt, gsi, vec_stmt,
4377 PHI_RESULT (VEC_index (gimple, phis, 0)),
4378 reduc_index);
4379 /* Multiple types are not supported for condition. */
4380 break;
4381 }
4382
4383 /* Handle uses. */
4384 if (j == 0)
4385 {
4386 tree op0, op1 = NULL_TREE;
4387
4388 op0 = ops[!reduc_index];
4389 if (op_type == ternary_op)
4390 {
4391 if (reduc_index == 0)
4392 op1 = ops[2];
4393 else
4394 op1 = ops[1];
4395 }
4396
4397 if (slp_node)
4398 vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0, &vec_oprnds1,
4399 -1);
4400 else
4401 {
4402 loop_vec_def0 = vect_get_vec_def_for_operand (ops[!reduc_index],
4403 stmt, NULL);
4404 VEC_quick_push (tree, vec_oprnds0, loop_vec_def0);
4405 if (op_type == ternary_op)
4406 {
4407 loop_vec_def1 = vect_get_vec_def_for_operand (op1, stmt,
4408 NULL);
4409 VEC_quick_push (tree, vec_oprnds1, loop_vec_def1);
4410 }
4411 }
4412 }
4413 else
4414 {
4415 if (!slp_node)
4416 {
4417 enum vect_def_type dt = vect_unknown_def_type; /* Dummy */
4418 loop_vec_def0 = vect_get_vec_def_for_stmt_copy (dt, loop_vec_def0);
4419 VEC_replace (tree, vec_oprnds0, 0, loop_vec_def0);
4420 if (op_type == ternary_op)
4421 {
4422 loop_vec_def1 = vect_get_vec_def_for_stmt_copy (dt,
4423 loop_vec_def1);
4424 VEC_replace (tree, vec_oprnds1, 0, loop_vec_def1);
4425 }
4426 }
4427
4428 if (single_defuse_cycle)
4429 reduc_def = gimple_assign_lhs (new_stmt);
4430
4431 STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi;
4432 }
4433
4434 FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, def0)
4435 {
4436 if (slp_node)
4437 reduc_def = PHI_RESULT (VEC_index (gimple, phis, i));
4438 else
4439 {
4440 if (!single_defuse_cycle || j == 0)
4441 reduc_def = PHI_RESULT (new_phi);
4442 }
4443
4444 def1 = ((op_type == ternary_op)
4445 ? VEC_index (tree, vec_oprnds1, i) : NULL);
4446 if (op_type == binary_op)
4447 {
4448 if (reduc_index == 0)
4449 expr = build2 (code, vectype_out, reduc_def, def0);
4450 else
4451 expr = build2 (code, vectype_out, def0, reduc_def);
4452 }
4453 else
4454 {
4455 if (reduc_index == 0)
4456 expr = build3 (code, vectype_out, reduc_def, def0, def1);
4457 else
4458 {
4459 if (reduc_index == 1)
4460 expr = build3 (code, vectype_out, def0, reduc_def, def1);
4461 else
4462 expr = build3 (code, vectype_out, def0, def1, reduc_def);
4463 }
4464 }
4465
4466 new_stmt = gimple_build_assign (vec_dest, expr);
4467 new_temp = make_ssa_name (vec_dest, new_stmt);
4468 gimple_assign_set_lhs (new_stmt, new_temp);
4469 vect_finish_stmt_generation (stmt, new_stmt, gsi);
4470 if (slp_node)
4471 {
4472 VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
4473 VEC_quick_push (tree, vect_defs, new_temp);
4474 }
4475 else
4476 VEC_replace (tree, vect_defs, 0, new_temp);
4477 }
4478
4479 if (slp_node)
4480 continue;
4481
4482 if (j == 0)
4483 STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
4484 else
4485 STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4486
4487 prev_stmt_info = vinfo_for_stmt (new_stmt);
4488 prev_phi_info = vinfo_for_stmt (new_phi);
4489 }
4490
4491 /* Finalize the reduction-phi (set its arguments) and create the
4492 epilog reduction code. */
4493 if ((!single_defuse_cycle || code == COND_EXPR) && !slp_node)
4494 {
4495 new_temp = gimple_assign_lhs (*vec_stmt);
4496 VEC_replace (tree, vect_defs, 0, new_temp);
4497 }
4498
4499 vect_create_epilog_for_reduction (vect_defs, stmt, epilog_copies,
4500 epilog_reduc_code, phis, reduc_index,
4501 double_reduc, slp_node);
4502
4503 VEC_free (gimple, heap, phis);
4504 VEC_free (tree, heap, vec_oprnds0);
4505 if (vec_oprnds1)
4506 VEC_free (tree, heap, vec_oprnds1);
4507
4508 return true;
4509 }
4510
4511 /* Function vect_min_worthwhile_factor.
4512
4513 For a loop where we could vectorize the operation indicated by CODE,
4514 return the minimum vectorization factor that makes it worthwhile
4515 to use generic vectors. */
4516 int
4517 vect_min_worthwhile_factor (enum tree_code code)
4518 {
4519 switch (code)
4520 {
4521 case PLUS_EXPR:
4522 case MINUS_EXPR:
4523 case NEGATE_EXPR:
4524 return 4;
4525
4526 case BIT_AND_EXPR:
4527 case BIT_IOR_EXPR:
4528 case BIT_XOR_EXPR:
4529 case BIT_NOT_EXPR:
4530 return 2;
4531
4532 default:
4533 return INT_MAX;
4534 }
4535 }
4536
4537
4538 /* Function vectorizable_induction
4539
4540 Check if PHI performs an induction computation that can be vectorized.
4541 If VEC_STMT is also passed, vectorize the induction PHI: create a vectorized
4542 phi to replace it, put it in VEC_STMT, and add it to the same basic block.
4543 Return FALSE if not a vectorizable STMT, TRUE otherwise. */
4544
4545 bool
4546 vectorizable_induction (gimple phi, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
4547 gimple *vec_stmt)
4548 {
4549 stmt_vec_info stmt_info = vinfo_for_stmt (phi);
4550 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4551 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4552 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4553 int nunits = TYPE_VECTOR_SUBPARTS (vectype);
4554 int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
4555 tree vec_def;
4556
4557 gcc_assert (ncopies >= 1);
4558 /* FORNOW. This restriction should be relaxed. */
4559 if (nested_in_vect_loop_p (loop, phi) && ncopies > 1)
4560 {
4561 if (vect_print_dump_info (REPORT_DETAILS))
4562 fprintf (vect_dump, "multiple types in nested loop.");
4563 return false;
4564 }
4565
4566 if (!STMT_VINFO_RELEVANT_P (stmt_info))
4567 return false;
4568
4569 /* FORNOW: SLP not supported. */
4570 if (STMT_SLP_TYPE (stmt_info))
4571 return false;
4572
4573 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def);
4574
4575 if (gimple_code (phi) != GIMPLE_PHI)
4576 return false;
4577
4578 if (!vec_stmt) /* transformation not required. */
4579 {
4580 STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
4581 if (vect_print_dump_info (REPORT_DETAILS))
4582 fprintf (vect_dump, "=== vectorizable_induction ===");
4583 vect_model_induction_cost (stmt_info, ncopies);
4584 return true;
4585 }
4586
4587 /** Transform. **/
4588
4589 if (vect_print_dump_info (REPORT_DETAILS))
4590 fprintf (vect_dump, "transform induction phi.");
4591
4592 vec_def = get_initial_def_for_induction (phi);
4593 *vec_stmt = SSA_NAME_DEF_STMT (vec_def);
4594 return true;
4595 }
4596
4597 /* Function vectorizable_live_operation.
4598
4599 STMT computes a value that is used outside the loop. Check if
4600 it can be supported. */
4601
4602 bool
4603 vectorizable_live_operation (gimple stmt,
4604 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
4605 gimple *vec_stmt ATTRIBUTE_UNUSED)
4606 {
4607 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4608 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4609 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4610 int i;
4611 int op_type;
4612 tree op;
4613 tree def;
4614 gimple def_stmt;
4615 enum vect_def_type dt;
4616 enum tree_code code;
4617 enum gimple_rhs_class rhs_class;
4618
4619 gcc_assert (STMT_VINFO_LIVE_P (stmt_info));
4620
4621 if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)
4622 return false;
4623
4624 if (!is_gimple_assign (stmt))
4625 return false;
4626
4627 if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
4628 return false;
4629
4630 /* FORNOW. CHECKME. */
4631 if (nested_in_vect_loop_p (loop, stmt))
4632 return false;
4633
4634 code = gimple_assign_rhs_code (stmt);
4635 op_type = TREE_CODE_LENGTH (code);
4636 rhs_class = get_gimple_rhs_class (code);
4637 gcc_assert (rhs_class != GIMPLE_UNARY_RHS || op_type == unary_op);
4638 gcc_assert (rhs_class != GIMPLE_BINARY_RHS || op_type == binary_op);
4639
4640 /* FORNOW: support only if all uses are invariant. This means
4641 that the scalar operations can remain in place, unvectorized.
4642 The original last scalar value that they compute will be used. */
4643
4644 for (i = 0; i < op_type; i++)
4645 {
4646 if (rhs_class == GIMPLE_SINGLE_RHS)
4647 op = TREE_OPERAND (gimple_op (stmt, 1), i);
4648 else
4649 op = gimple_op (stmt, i + 1);
4650 if (op
4651 && !vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def, &dt))
4652 {
4653 if (vect_print_dump_info (REPORT_DETAILS))
4654 fprintf (vect_dump, "use not simple.");
4655 return false;
4656 }
4657
4658 if (dt != vect_external_def && dt != vect_constant_def)
4659 return false;
4660 }
4661
4662 /* No transformation is required for the cases we currently support. */
4663 return true;
4664 }
4665
4666 /* Kill any debug uses outside LOOP of SSA names defined in STMT. */
4667
4668 static void
4669 vect_loop_kill_debug_uses (struct loop *loop, gimple stmt)
4670 {
4671 ssa_op_iter op_iter;
4672 imm_use_iterator imm_iter;
4673 def_operand_p def_p;
4674 gimple ustmt;
4675
4676 FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
4677 {
4678 FOR_EACH_IMM_USE_STMT (ustmt, imm_iter, DEF_FROM_PTR (def_p))
4679 {
4680 basic_block bb;
4681
4682 if (!is_gimple_debug (ustmt))
4683 continue;
4684
4685 bb = gimple_bb (ustmt);
4686
4687 if (!flow_bb_inside_loop_p (loop, bb))
4688 {
4689 if (gimple_debug_bind_p (ustmt))
4690 {
4691 if (vect_print_dump_info (REPORT_DETAILS))
4692 fprintf (vect_dump, "killing debug use");
4693
4694 gimple_debug_bind_reset_value (ustmt);
4695 update_stmt (ustmt);
4696 }
4697 else
4698 gcc_unreachable ();
4699 }
4700 }
4701 }
4702 }
4703
4704 /* Function vect_transform_loop.
4705
4706 The analysis phase has determined that the loop is vectorizable.
4707 Vectorize the loop - created vectorized stmts to replace the scalar
4708 stmts in the loop, and update the loop exit condition. */
4709
4710 void
4711 vect_transform_loop (loop_vec_info loop_vinfo)
4712 {
4713 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4714 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
4715 int nbbs = loop->num_nodes;
4716 gimple_stmt_iterator si;
4717 int i;
4718 tree ratio = NULL;
4719 int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
4720 bool strided_store;
4721 bool slp_scheduled = false;
4722 unsigned int nunits;
4723 tree cond_expr = NULL_TREE;
4724 gimple_seq cond_expr_stmt_list = NULL;
4725 bool do_peeling_for_loop_bound;
4726
4727 if (vect_print_dump_info (REPORT_DETAILS))
4728 fprintf (vect_dump, "=== vec_transform_loop ===");
4729
4730 /* Peel the loop if there are data refs with unknown alignment.
4731 Only one data ref with unknown store is allowed. */
4732
4733 if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
4734 vect_do_peeling_for_alignment (loop_vinfo);
4735
4736 do_peeling_for_loop_bound
4737 = (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
4738 || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
4739 && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0));
4740
4741 if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
4742 || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
4743 vect_loop_versioning (loop_vinfo,
4744 !do_peeling_for_loop_bound,
4745 &cond_expr, &cond_expr_stmt_list);
4746
4747 /* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
4748 compile time constant), or it is a constant that doesn't divide by the
4749 vectorization factor, then an epilog loop needs to be created.
4750 We therefore duplicate the loop: the original loop will be vectorized,
4751 and will compute the first (n/VF) iterations. The second copy of the loop
4752 will remain scalar and will compute the remaining (n%VF) iterations.
4753 (VF is the vectorization factor). */
4754
4755 if (do_peeling_for_loop_bound)
4756 vect_do_peeling_for_loop_bound (loop_vinfo, &ratio,
4757 cond_expr, cond_expr_stmt_list);
4758 else
4759 ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
4760 LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
4761
4762 /* 1) Make sure the loop header has exactly two entries
4763 2) Make sure we have a preheader basic block. */
4764
4765 gcc_assert (EDGE_COUNT (loop->header->preds) == 2);
4766
4767 split_edge (loop_preheader_edge (loop));
4768
4769 /* FORNOW: the vectorizer supports only loops which body consist
4770 of one basic block (header + empty latch). When the vectorizer will
4771 support more involved loop forms, the order by which the BBs are
4772 traversed need to be reconsidered. */
4773
4774 for (i = 0; i < nbbs; i++)
4775 {
4776 basic_block bb = bbs[i];
4777 stmt_vec_info stmt_info;
4778 gimple phi;
4779
4780 for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
4781 {
4782 phi = gsi_stmt (si);
4783 if (vect_print_dump_info (REPORT_DETAILS))
4784 {
4785 fprintf (vect_dump, "------>vectorizing phi: ");
4786 print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
4787 }
4788 stmt_info = vinfo_for_stmt (phi);
4789 if (!stmt_info)
4790 continue;
4791
4792 if (MAY_HAVE_DEBUG_STMTS && !STMT_VINFO_LIVE_P (stmt_info))
4793 vect_loop_kill_debug_uses (loop, phi);
4794
4795 if (!STMT_VINFO_RELEVANT_P (stmt_info)
4796 && !STMT_VINFO_LIVE_P (stmt_info))
4797 continue;
4798
4799 if ((TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info))
4800 != (unsigned HOST_WIDE_INT) vectorization_factor)
4801 && vect_print_dump_info (REPORT_DETAILS))
4802 fprintf (vect_dump, "multiple-types.");
4803
4804 if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def)
4805 {
4806 if (vect_print_dump_info (REPORT_DETAILS))
4807 fprintf (vect_dump, "transform phi.");
4808 vect_transform_stmt (phi, NULL, NULL, NULL, NULL);
4809 }
4810 }
4811
4812 for (si = gsi_start_bb (bb); !gsi_end_p (si);)
4813 {
4814 gimple stmt = gsi_stmt (si);
4815 bool is_store;
4816
4817 if (vect_print_dump_info (REPORT_DETAILS))
4818 {
4819 fprintf (vect_dump, "------>vectorizing statement: ");
4820 print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4821 }
4822
4823 stmt_info = vinfo_for_stmt (stmt);
4824
4825 /* vector stmts created in the outer-loop during vectorization of
4826 stmts in an inner-loop may not have a stmt_info, and do not
4827 need to be vectorized. */
4828 if (!stmt_info)
4829 {
4830 gsi_next (&si);
4831 continue;
4832 }
4833
4834 if (MAY_HAVE_DEBUG_STMTS && !STMT_VINFO_LIVE_P (stmt_info))
4835 vect_loop_kill_debug_uses (loop, stmt);
4836
4837 if (!STMT_VINFO_RELEVANT_P (stmt_info)
4838 && !STMT_VINFO_LIVE_P (stmt_info))
4839 {
4840 gsi_next (&si);
4841 continue;
4842 }
4843
4844 gcc_assert (STMT_VINFO_VECTYPE (stmt_info));
4845 nunits =
4846 (unsigned int) TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info));
4847 if (!STMT_SLP_TYPE (stmt_info)
4848 && nunits != (unsigned int) vectorization_factor
4849 && vect_print_dump_info (REPORT_DETAILS))
4850 /* For SLP VF is set according to unrolling factor, and not to
4851 vector size, hence for SLP this print is not valid. */
4852 fprintf (vect_dump, "multiple-types.");
4853
4854 /* SLP. Schedule all the SLP instances when the first SLP stmt is
4855 reached. */
4856 if (STMT_SLP_TYPE (stmt_info))
4857 {
4858 if (!slp_scheduled)
4859 {
4860 slp_scheduled = true;
4861
4862 if (vect_print_dump_info (REPORT_DETAILS))
4863 fprintf (vect_dump, "=== scheduling SLP instances ===");
4864
4865 vect_schedule_slp (loop_vinfo, NULL);
4866 }
4867
4868 /* Hybrid SLP stmts must be vectorized in addition to SLP. */
4869 if (!vinfo_for_stmt (stmt) || PURE_SLP_STMT (stmt_info))
4870 {
4871 gsi_next (&si);
4872 continue;
4873 }
4874 }
4875
4876 /* -------- vectorize statement ------------ */
4877 if (vect_print_dump_info (REPORT_DETAILS))
4878 fprintf (vect_dump, "transform statement.");
4879
4880 strided_store = false;
4881 is_store = vect_transform_stmt (stmt, &si, &strided_store, NULL, NULL);
4882 if (is_store)
4883 {
4884 if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
4885 {
4886 /* Interleaving. If IS_STORE is TRUE, the vectorization of the
4887 interleaving chain was completed - free all the stores in
4888 the chain. */
4889 vect_remove_stores (DR_GROUP_FIRST_DR (stmt_info));
4890 gsi_remove (&si, true);
4891 continue;
4892 }
4893 else
4894 {
4895 /* Free the attached stmt_vec_info and remove the stmt. */
4896 free_stmt_vec_info (stmt);
4897 gsi_remove (&si, true);
4898 continue;
4899 }
4900 }
4901 gsi_next (&si);
4902 } /* stmts in BB */
4903 } /* BBs in loop */
4904
4905 slpeel_make_loop_iterate_ntimes (loop, ratio);
4906
4907 /* The memory tags and pointers in vectorized statements need to
4908 have their SSA forms updated. FIXME, why can't this be delayed
4909 until all the loops have been transformed? */
4910 update_ssa (TODO_update_ssa);
4911
4912 if (vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS))
4913 fprintf (vect_dump, "LOOP VECTORIZED.");
4914 if (loop->inner && vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS))
4915 fprintf (vect_dump, "OUTER LOOP VECTORIZED.");
4916 }