OSDN Git Service

* cgraph.h (cgraph_local_info): Remove for_functions_valid.
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-data-refs.c
1 /* Data References Analysis and Manipulation Utilities for 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>
5    and 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 "target.h"
30 #include "basic-block.h"
31 #include "diagnostic.h"
32 #include "tree-flow.h"
33 #include "tree-dump.h"
34 #include "cfgloop.h"
35 #include "expr.h"
36 #include "optabs.h"
37 #include "tree-chrec.h"
38 #include "tree-scalar-evolution.h"
39 #include "tree-vectorizer.h"
40 #include "toplev.h"
41
42
43 /* Return the smallest scalar part of STMT.
44    This is used to determine the vectype of the stmt. We generally set the
45    vectype according to the type of the result (lhs). For stmts whose
46    result-type is different than the type of the arguments (e.g., demotion,
47    promotion), vectype will be reset appropriately (later).  Note that we have
48    to visit the smallest datatype in this function, because that determines the
49    VF. If the smallest datatype in the loop is present only as the rhs of a
50    promotion operation - we'd miss it.
51    Such a case, where a variable of this datatype does not appear in the lhs
52    anywhere in the loop, can only occur if it's an invariant: e.g.:
53    'int_x = (int) short_inv', which we'd expect to have been optimized away by
54    invariant motion. However, we cannot rely on invariant motion to always take
55    invariants out of the loop, and so in the case of promotion we also have to
56    check the rhs.
57    LHS_SIZE_UNIT and RHS_SIZE_UNIT contain the sizes of the corresponding
58    types.  */
59
60 tree
61 vect_get_smallest_scalar_type (gimple stmt, HOST_WIDE_INT *lhs_size_unit,
62                                HOST_WIDE_INT *rhs_size_unit)
63 {
64   tree scalar_type = gimple_expr_type (stmt);
65   HOST_WIDE_INT lhs, rhs;
66
67   lhs = rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
68
69   if (is_gimple_assign (stmt)
70       && (gimple_assign_cast_p (stmt)
71           || gimple_assign_rhs_code (stmt) == WIDEN_MULT_EXPR
72           || gimple_assign_rhs_code (stmt) == FLOAT_EXPR))
73     {
74       tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
75
76       rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type));
77       if (rhs < lhs)
78         scalar_type = rhs_type;
79     }
80
81   *lhs_size_unit = lhs;
82   *rhs_size_unit = rhs;
83   return scalar_type;
84 }
85
86
87 /* Find the place of the data-ref in STMT in the interleaving chain that starts
88    from FIRST_STMT. Return -1 if the data-ref is not a part of the chain.  */
89
90 int
91 vect_get_place_in_interleaving_chain (gimple stmt, gimple first_stmt)
92 {
93   gimple next_stmt = first_stmt;
94   int result = 0;
95
96   if (first_stmt != DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)))
97     return -1;
98
99   while (next_stmt && next_stmt != stmt)
100     {
101       result++;
102       next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
103     }
104
105   if (next_stmt)
106     return result;
107   else
108     return -1;
109 }
110
111
112 /* Function vect_insert_into_interleaving_chain.
113
114    Insert DRA into the interleaving chain of DRB according to DRA's INIT.  */
115
116 static void
117 vect_insert_into_interleaving_chain (struct data_reference *dra,
118                                      struct data_reference *drb)
119 {
120   gimple prev, next;
121   tree next_init;
122   stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
123   stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
124
125   prev = DR_GROUP_FIRST_DR (stmtinfo_b);
126   next = DR_GROUP_NEXT_DR (vinfo_for_stmt (prev));
127   while (next)
128     {
129       next_init = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (next)));
130       if (tree_int_cst_compare (next_init, DR_INIT (dra)) > 0)
131         {
132           /* Insert here.  */
133           DR_GROUP_NEXT_DR (vinfo_for_stmt (prev)) = DR_STMT (dra);
134           DR_GROUP_NEXT_DR (stmtinfo_a) = next;
135           return;
136         }
137       prev = next;
138       next = DR_GROUP_NEXT_DR (vinfo_for_stmt (prev));
139     }
140
141   /* We got to the end of the list. Insert here.  */
142   DR_GROUP_NEXT_DR (vinfo_for_stmt (prev)) = DR_STMT (dra);
143   DR_GROUP_NEXT_DR (stmtinfo_a) = NULL;
144 }
145
146
147 /* Function vect_update_interleaving_chain.
148
149    For two data-refs DRA and DRB that are a part of a chain interleaved data
150    accesses, update the interleaving chain. DRB's INIT is smaller than DRA's.
151
152    There are four possible cases:
153    1. New stmts - both DRA and DRB are not a part of any chain:
154       FIRST_DR = DRB
155       NEXT_DR (DRB) = DRA
156    2. DRB is a part of a chain and DRA is not:
157       no need to update FIRST_DR
158       no need to insert DRB
159       insert DRA according to init
160    3. DRA is a part of a chain and DRB is not:
161       if (init of FIRST_DR > init of DRB)
162           FIRST_DR = DRB
163           NEXT(FIRST_DR) = previous FIRST_DR
164       else
165           insert DRB according to its init
166    4. both DRA and DRB are in some interleaving chains:
167       choose the chain with the smallest init of FIRST_DR
168       insert the nodes of the second chain into the first one.  */
169
170 static void
171 vect_update_interleaving_chain (struct data_reference *drb,
172                                 struct data_reference *dra)
173 {
174   stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
175   stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
176   tree next_init, init_dra_chain, init_drb_chain;
177   gimple first_a, first_b;
178   tree node_init;
179   gimple node, prev, next, first_stmt;
180
181   /* 1. New stmts - both DRA and DRB are not a part of any chain.   */
182   if (!DR_GROUP_FIRST_DR (stmtinfo_a) && !DR_GROUP_FIRST_DR (stmtinfo_b))
183     {
184       DR_GROUP_FIRST_DR (stmtinfo_a) = DR_STMT (drb);
185       DR_GROUP_FIRST_DR (stmtinfo_b) = DR_STMT (drb);
186       DR_GROUP_NEXT_DR (stmtinfo_b) = DR_STMT (dra);
187       return;
188     }
189
190   /* 2. DRB is a part of a chain and DRA is not.  */
191   if (!DR_GROUP_FIRST_DR (stmtinfo_a) && DR_GROUP_FIRST_DR (stmtinfo_b))
192     {
193       DR_GROUP_FIRST_DR (stmtinfo_a) = DR_GROUP_FIRST_DR (stmtinfo_b);
194       /* Insert DRA into the chain of DRB.  */
195       vect_insert_into_interleaving_chain (dra, drb);
196       return;
197     }
198
199   /* 3. DRA is a part of a chain and DRB is not.  */
200   if (DR_GROUP_FIRST_DR (stmtinfo_a) && !DR_GROUP_FIRST_DR (stmtinfo_b))
201     {
202       gimple old_first_stmt = DR_GROUP_FIRST_DR (stmtinfo_a);
203       tree init_old = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (
204                                                               old_first_stmt)));
205       gimple tmp;
206
207       if (tree_int_cst_compare (init_old, DR_INIT (drb)) > 0)
208         {
209           /* DRB's init is smaller than the init of the stmt previously marked
210              as the first stmt of the interleaving chain of DRA. Therefore, we
211              update FIRST_STMT and put DRB in the head of the list.  */
212           DR_GROUP_FIRST_DR (stmtinfo_b) = DR_STMT (drb);
213           DR_GROUP_NEXT_DR (stmtinfo_b) = old_first_stmt;
214
215           /* Update all the stmts in the list to point to the new FIRST_STMT.  */
216           tmp = old_first_stmt;
217           while (tmp)
218             {
219               DR_GROUP_FIRST_DR (vinfo_for_stmt (tmp)) = DR_STMT (drb);
220               tmp = DR_GROUP_NEXT_DR (vinfo_for_stmt (tmp));
221             }
222         }
223       else
224         {
225           /* Insert DRB in the list of DRA.  */
226           vect_insert_into_interleaving_chain (drb, dra);
227           DR_GROUP_FIRST_DR (stmtinfo_b) = DR_GROUP_FIRST_DR (stmtinfo_a);
228         }
229       return;
230     }
231
232   /* 4. both DRA and DRB are in some interleaving chains.  */
233   first_a = DR_GROUP_FIRST_DR (stmtinfo_a);
234   first_b = DR_GROUP_FIRST_DR (stmtinfo_b);
235   if (first_a == first_b)
236     return;
237   init_dra_chain = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_a)));
238   init_drb_chain = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_b)));
239
240   if (tree_int_cst_compare (init_dra_chain, init_drb_chain) > 0)
241     {
242       /* Insert the nodes of DRA chain into the DRB chain.
243          After inserting a node, continue from this node of the DRB chain (don't
244          start from the beginning.  */
245       node = DR_GROUP_FIRST_DR (stmtinfo_a);
246       prev = DR_GROUP_FIRST_DR (stmtinfo_b);
247       first_stmt = first_b;
248     }
249   else
250     {
251       /* Insert the nodes of DRB chain into the DRA chain.
252          After inserting a node, continue from this node of the DRA chain (don't
253          start from the beginning.  */
254       node = DR_GROUP_FIRST_DR (stmtinfo_b);
255       prev = DR_GROUP_FIRST_DR (stmtinfo_a);
256       first_stmt = first_a;
257     }
258
259   while (node)
260     {
261       node_init = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (node)));
262       next = DR_GROUP_NEXT_DR (vinfo_for_stmt (prev));
263       while (next)
264         {
265           next_init = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (next)));
266           if (tree_int_cst_compare (next_init, node_init) > 0)
267             {
268               /* Insert here.  */
269               DR_GROUP_NEXT_DR (vinfo_for_stmt (prev)) = node;
270               DR_GROUP_NEXT_DR (vinfo_for_stmt (node)) = next;
271               prev = node;
272               break;
273             }
274           prev = next;
275           next = DR_GROUP_NEXT_DR (vinfo_for_stmt (prev));
276         }
277       if (!next)
278         {
279           /* We got to the end of the list. Insert here.  */
280           DR_GROUP_NEXT_DR (vinfo_for_stmt (prev)) = node;
281           DR_GROUP_NEXT_DR (vinfo_for_stmt (node)) = NULL;
282           prev = node;
283         }
284       DR_GROUP_FIRST_DR (vinfo_for_stmt (node)) = first_stmt;
285       node = DR_GROUP_NEXT_DR (vinfo_for_stmt (node));
286     }
287 }
288
289
290 /* Function vect_equal_offsets.
291
292    Check if OFFSET1 and OFFSET2 are identical expressions.  */
293
294 static bool
295 vect_equal_offsets (tree offset1, tree offset2)
296 {
297   bool res;
298
299   STRIP_NOPS (offset1);
300   STRIP_NOPS (offset2);
301
302   if (offset1 == offset2)
303     return true;
304
305   if (TREE_CODE (offset1) != TREE_CODE (offset2)
306       || (!BINARY_CLASS_P (offset1) && !UNARY_CLASS_P (offset1)))
307     return false;
308
309   res = vect_equal_offsets (TREE_OPERAND (offset1, 0),
310                             TREE_OPERAND (offset2, 0));
311
312   if (!res || !BINARY_CLASS_P (offset1))
313     return res;
314
315   res = vect_equal_offsets (TREE_OPERAND (offset1, 1),
316                             TREE_OPERAND (offset2, 1));
317
318   return res;
319 }
320
321
322 /* Function vect_check_interleaving.
323
324    Check if DRA and DRB are a part of interleaving. In case they are, insert
325    DRA and DRB in an interleaving chain.  */
326
327 static bool
328 vect_check_interleaving (struct data_reference *dra,
329                          struct data_reference *drb)
330 {
331   HOST_WIDE_INT type_size_a, type_size_b, diff_mod_size, step, init_a, init_b;
332
333   /* Check that the data-refs have same first location (except init) and they
334      are both either store or load (not load and store).  */
335   if ((DR_BASE_ADDRESS (dra) != DR_BASE_ADDRESS (drb)
336        && (TREE_CODE (DR_BASE_ADDRESS (dra)) != ADDR_EXPR
337            || TREE_CODE (DR_BASE_ADDRESS (drb)) != ADDR_EXPR
338            || TREE_OPERAND (DR_BASE_ADDRESS (dra), 0)
339            != TREE_OPERAND (DR_BASE_ADDRESS (drb),0)))
340       || !vect_equal_offsets (DR_OFFSET (dra), DR_OFFSET (drb))
341       || !tree_int_cst_compare (DR_INIT (dra), DR_INIT (drb))
342       || DR_IS_READ (dra) != DR_IS_READ (drb))
343     return false;
344
345   /* Check:
346      1. data-refs are of the same type
347      2. their steps are equal
348      3. the step (if greater than zero) is greater than the difference between
349         data-refs' inits.  */
350   type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
351   type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
352
353   if (type_size_a != type_size_b
354       || tree_int_cst_compare (DR_STEP (dra), DR_STEP (drb))
355       || !types_compatible_p (TREE_TYPE (DR_REF (dra)),
356                               TREE_TYPE (DR_REF (drb))))
357     return false;
358
359   init_a = TREE_INT_CST_LOW (DR_INIT (dra));
360   init_b = TREE_INT_CST_LOW (DR_INIT (drb));
361   step = TREE_INT_CST_LOW (DR_STEP (dra));
362
363   if (init_a > init_b)
364     {
365       /* If init_a == init_b + the size of the type * k, we have an interleaving,
366          and DRB is accessed before DRA.  */
367       diff_mod_size = (init_a - init_b) % type_size_a;
368
369       if (step && (init_a - init_b) > step)
370          return false;
371
372       if (diff_mod_size == 0)
373         {
374           vect_update_interleaving_chain (drb, dra);
375           if (vect_print_dump_info (REPORT_DR_DETAILS))
376             {
377               fprintf (vect_dump, "Detected interleaving ");
378               print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
379               fprintf (vect_dump, " and ");
380               print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
381             }
382           return true;
383         }
384     }
385   else
386     {
387       /* If init_b == init_a + the size of the type * k, we have an
388          interleaving, and DRA is accessed before DRB.  */
389       diff_mod_size = (init_b - init_a) % type_size_a;
390
391       if (step && (init_b - init_a) > step)
392          return false;
393
394       if (diff_mod_size == 0)
395         {
396           vect_update_interleaving_chain (dra, drb);
397           if (vect_print_dump_info (REPORT_DR_DETAILS))
398             {
399               fprintf (vect_dump, "Detected interleaving ");
400               print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
401               fprintf (vect_dump, " and ");
402               print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
403             }
404           return true;
405         }
406     }
407
408   return false;
409 }
410
411 /* Check if data references pointed by DR_I and DR_J are same or
412    belong to same interleaving group.  Return FALSE if drs are
413    different, otherwise return TRUE.  */
414
415 static bool
416 vect_same_range_drs (data_reference_p dr_i, data_reference_p dr_j)
417 {
418   gimple stmt_i = DR_STMT (dr_i);
419   gimple stmt_j = DR_STMT (dr_j);
420
421   if (operand_equal_p (DR_REF (dr_i), DR_REF (dr_j), 0)
422       || (DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt_i))
423             && DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt_j))
424             && (DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt_i))
425                 == DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt_j)))))
426     return true;
427   else
428     return false;
429 }
430
431 /* If address ranges represented by DDR_I and DDR_J are equal,
432    return TRUE, otherwise return FALSE.  */
433
434 static bool
435 vect_vfa_range_equal (ddr_p ddr_i, ddr_p ddr_j)
436 {
437   if ((vect_same_range_drs (DDR_A (ddr_i), DDR_A (ddr_j))
438        && vect_same_range_drs (DDR_B (ddr_i), DDR_B (ddr_j)))
439       || (vect_same_range_drs (DDR_A (ddr_i), DDR_B (ddr_j))
440           && vect_same_range_drs (DDR_B (ddr_i), DDR_A (ddr_j))))
441     return true;
442   else
443     return false;
444 }
445
446 /* Insert DDR into LOOP_VINFO list of ddrs that may alias and need to be
447    tested at run-time.  Return TRUE if DDR was successfully inserted.
448    Return false if versioning is not supported.  */
449
450 static bool
451 vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
452 {
453   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
454
455   if ((unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS) == 0)
456     return false;
457
458   if (vect_print_dump_info (REPORT_DR_DETAILS))
459     {
460       fprintf (vect_dump, "mark for run-time aliasing test between ");
461       print_generic_expr (vect_dump, DR_REF (DDR_A (ddr)), TDF_SLIM);
462       fprintf (vect_dump, " and ");
463       print_generic_expr (vect_dump, DR_REF (DDR_B (ddr)), TDF_SLIM);
464     }
465
466   if (optimize_loop_nest_for_size_p (loop))
467     {
468       if (vect_print_dump_info (REPORT_DR_DETAILS))
469         fprintf (vect_dump, "versioning not supported when optimizing for size.");
470       return false;
471     }
472
473   /* FORNOW: We don't support versioning with outer-loop vectorization.  */
474   if (loop->inner)
475     {
476       if (vect_print_dump_info (REPORT_DR_DETAILS))
477         fprintf (vect_dump, "versioning not yet supported for outer-loops.");
478       return false;
479     }
480
481   VEC_safe_push (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), ddr);
482   return true;
483 }
484
485
486 /* Function vect_analyze_data_ref_dependence.
487
488    Return TRUE if there (might) exist a dependence between a memory-reference
489    DRA and a memory-reference DRB.  When versioning for alias may check a
490    dependence at run-time, return FALSE.  Adjust *MAX_VF according to
491    the data dependence.  */
492
493 static bool
494 vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
495                                   loop_vec_info loop_vinfo, int *max_vf)
496 {
497   unsigned int i;
498   struct loop *loop = NULL;
499   struct data_reference *dra = DDR_A (ddr);
500   struct data_reference *drb = DDR_B (ddr);
501   stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
502   stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
503   lambda_vector dist_v;
504   unsigned int loop_depth;
505
506   /* Don't bother to analyze statements marked as unvectorizable.  */
507   if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a)
508       || !STMT_VINFO_VECTORIZABLE (stmtinfo_b))
509     return false;
510
511   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
512     {
513       /* Independent data accesses.  */
514       vect_check_interleaving (dra, drb);
515       return false;
516     }
517
518   if (loop_vinfo)
519     loop = LOOP_VINFO_LOOP (loop_vinfo);
520
521   if ((DR_IS_READ (dra) && DR_IS_READ (drb) && loop_vinfo) || dra == drb)
522     return false;
523
524   if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
525     {
526       if (loop_vinfo)
527         {
528           if (vect_print_dump_info (REPORT_DR_DETAILS))
529             {
530               fprintf (vect_dump, "versioning for alias required: "
531                                   "can't determine dependence between ");
532               print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
533               fprintf (vect_dump, " and ");
534               print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
535             }
536
537           /* Add to list of ddrs that need to be tested at run-time.  */
538           return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
539         }
540
541       /* When vectorizing a basic block unknown depnedence can still mean
542          strided access.  */
543       if (vect_check_interleaving (dra, drb))
544          return false;
545
546       if (vect_print_dump_info (REPORT_DR_DETAILS))
547         {
548           fprintf (vect_dump, "can't determine dependence between ");
549           print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
550           fprintf (vect_dump, " and ");
551           print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
552         }
553
554       /* Mark the statements as unvectorizable.  */
555       STMT_VINFO_VECTORIZABLE (stmtinfo_a) = false;
556       STMT_VINFO_VECTORIZABLE (stmtinfo_b) = false;
557
558       return false;
559     }
560
561   /* Versioning for alias is not yet supported for basic block SLP, and
562      dependence distance is unapplicable, hence, in case of known data
563      dependence, basic block vectorization is impossible for now.  */
564   if (!loop_vinfo)
565     {
566       if (dra != drb && vect_check_interleaving (dra, drb))
567         return false;
568
569       if (vect_print_dump_info (REPORT_DR_DETAILS))
570         {
571           fprintf (vect_dump, "determined dependence between ");
572           print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
573           fprintf (vect_dump, " and ");
574           print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
575         }
576
577       return true;
578     }
579
580   /* Loop-based vectorization and known data dependence.  */
581   if (DDR_NUM_DIST_VECTS (ddr) == 0)
582     {
583       if (vect_print_dump_info (REPORT_DR_DETAILS))
584         {
585           fprintf (vect_dump, "versioning for alias required: bad dist vector for ");
586           print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
587           fprintf (vect_dump, " and ");
588           print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
589         }
590       /* Add to list of ddrs that need to be tested at run-time.  */
591       return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
592     }
593
594   loop_depth = index_in_loop_nest (loop->num, DDR_LOOP_NEST (ddr));
595   for (i = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v); i++)
596     {
597       int dist = dist_v[loop_depth];
598
599       if (vect_print_dump_info (REPORT_DR_DETAILS))
600         fprintf (vect_dump, "dependence distance  = %d.", dist);
601
602       if (dist == 0)
603         {
604           if (vect_print_dump_info (REPORT_DR_DETAILS))
605             {
606               fprintf (vect_dump, "dependence distance == 0 between ");
607               print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
608               fprintf (vect_dump, " and ");
609               print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
610             }
611
612           /* For interleaving, mark that there is a read-write dependency if
613              necessary. We check before that one of the data-refs is store.  */
614           if (DR_IS_READ (dra))
615             DR_GROUP_READ_WRITE_DEPENDENCE (stmtinfo_a) = true;
616           else
617             {
618               if (DR_IS_READ (drb))
619                 DR_GROUP_READ_WRITE_DEPENDENCE (stmtinfo_b) = true;
620             }
621
622           continue;
623         }
624
625       if (dist > 0 && DDR_REVERSED_P (ddr))
626         {
627           /* If DDR_REVERSED_P the order of the data-refs in DDR was
628              reversed (to make distance vector positive), and the actual
629              distance is negative.  */
630           if (vect_print_dump_info (REPORT_DR_DETAILS))
631             fprintf (vect_dump, "dependence distance negative.");
632           continue;
633         }
634
635       if (abs (dist) >= 2
636           && abs (dist) < *max_vf)
637         {
638           /* The dependence distance requires reduction of the maximal
639              vectorization factor.  */
640           *max_vf = abs (dist);
641           if (vect_print_dump_info (REPORT_DR_DETAILS))
642             fprintf (vect_dump, "adjusting maximal vectorization factor to %i",
643                      *max_vf);
644         }
645
646       if (abs (dist) >= *max_vf)
647         {
648           /* Dependence distance does not create dependence, as far as
649              vectorization is concerned, in this case.  */
650           if (vect_print_dump_info (REPORT_DR_DETAILS))
651             fprintf (vect_dump, "dependence distance >= VF.");
652           continue;
653         }
654
655       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
656         {
657           fprintf (vect_dump, "not vectorized, possible dependence "
658                               "between data-refs ");
659           print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
660           fprintf (vect_dump, " and ");
661           print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
662         }
663
664       return true;
665     }
666
667   return false;
668 }
669
670 /* Function vect_analyze_data_ref_dependences.
671
672    Examine all the data references in the loop, and make sure there do not
673    exist any data dependences between them.  Set *MAX_VF according to
674    the maximum vectorization factor the data dependences allow.  */
675
676 bool
677 vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
678                                    bb_vec_info bb_vinfo, int *max_vf)
679 {
680   unsigned int i;
681   VEC (ddr_p, heap) *ddrs = NULL;
682   struct data_dependence_relation *ddr;
683
684   if (vect_print_dump_info (REPORT_DETAILS))
685     fprintf (vect_dump, "=== vect_analyze_dependences ===");
686
687   if (loop_vinfo)
688     ddrs = LOOP_VINFO_DDRS (loop_vinfo);
689   else
690     ddrs = BB_VINFO_DDRS (bb_vinfo);
691
692   for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
693     if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf))
694       return false;
695
696   return true;
697 }
698
699
700 /* Function vect_compute_data_ref_alignment
701
702    Compute the misalignment of the data reference DR.
703
704    Output:
705    1. If during the misalignment computation it is found that the data reference
706       cannot be vectorized then false is returned.
707    2. DR_MISALIGNMENT (DR) is defined.
708
709    FOR NOW: No analysis is actually performed. Misalignment is calculated
710    only for trivial cases. TODO.  */
711
712 static bool
713 vect_compute_data_ref_alignment (struct data_reference *dr)
714 {
715   gimple stmt = DR_STMT (dr);
716   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
717   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
718   struct loop *loop = NULL;
719   tree ref = DR_REF (dr);
720   tree vectype;
721   tree base, base_addr;
722   bool base_aligned;
723   tree misalign;
724   tree aligned_to, alignment;
725
726   if (vect_print_dump_info (REPORT_DETAILS))
727     fprintf (vect_dump, "vect_compute_data_ref_alignment:");
728
729   if (loop_vinfo)
730     loop = LOOP_VINFO_LOOP (loop_vinfo);
731
732   /* Initialize misalignment to unknown.  */
733   SET_DR_MISALIGNMENT (dr, -1);
734
735   misalign = DR_INIT (dr);
736   aligned_to = DR_ALIGNED_TO (dr);
737   base_addr = DR_BASE_ADDRESS (dr);
738   vectype = STMT_VINFO_VECTYPE (stmt_info);
739
740   /* In case the dataref is in an inner-loop of the loop that is being
741      vectorized (LOOP), we use the base and misalignment information
742      relative to the outer-loop (LOOP). This is ok only if the misalignment
743      stays the same throughout the execution of the inner-loop, which is why
744      we have to check that the stride of the dataref in the inner-loop evenly
745      divides by the vector size.  */
746   if (loop && nested_in_vect_loop_p (loop, stmt))
747     {
748       tree step = DR_STEP (dr);
749       HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
750
751       if (dr_step % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0)
752         {
753           if (vect_print_dump_info (REPORT_ALIGNMENT))
754             fprintf (vect_dump, "inner step divides the vector-size.");
755           misalign = STMT_VINFO_DR_INIT (stmt_info);
756           aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info);
757           base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
758         }
759       else
760         {
761           if (vect_print_dump_info (REPORT_ALIGNMENT))
762             fprintf (vect_dump, "inner step doesn't divide the vector-size.");
763           misalign = NULL_TREE;
764         }
765     }
766
767   base = build_fold_indirect_ref (base_addr);
768   alignment = ssize_int (TYPE_ALIGN (vectype)/BITS_PER_UNIT);
769
770   if ((aligned_to && tree_int_cst_compare (aligned_to, alignment) < 0)
771       || !misalign)
772     {
773       if (vect_print_dump_info (REPORT_ALIGNMENT))
774         {
775           fprintf (vect_dump, "Unknown alignment for access: ");
776           print_generic_expr (vect_dump, base, TDF_SLIM);
777         }
778       return true;
779     }
780
781   if ((DECL_P (base)
782        && tree_int_cst_compare (ssize_int (DECL_ALIGN_UNIT (base)),
783                                 alignment) >= 0)
784       || (TREE_CODE (base_addr) == SSA_NAME
785           && tree_int_cst_compare (ssize_int (TYPE_ALIGN_UNIT (TREE_TYPE (
786                                                       TREE_TYPE (base_addr)))),
787                                    alignment) >= 0))
788     base_aligned = true;
789   else
790     base_aligned = false;
791
792   if (!base_aligned)
793     {
794       /* Do not change the alignment of global variables if
795          flag_section_anchors is enabled.  */
796       if (!vect_can_force_dr_alignment_p (base, TYPE_ALIGN (vectype))
797           || (TREE_STATIC (base) && flag_section_anchors))
798         {
799           if (vect_print_dump_info (REPORT_DETAILS))
800             {
801               fprintf (vect_dump, "can't force alignment of ref: ");
802               print_generic_expr (vect_dump, ref, TDF_SLIM);
803             }
804           return true;
805         }
806
807       /* Force the alignment of the decl.
808          NOTE: This is the only change to the code we make during
809          the analysis phase, before deciding to vectorize the loop.  */
810       if (vect_print_dump_info (REPORT_DETAILS))
811         fprintf (vect_dump, "force alignment");
812       DECL_ALIGN (base) = TYPE_ALIGN (vectype);
813       DECL_USER_ALIGN (base) = 1;
814     }
815
816   /* At this point we assume that the base is aligned.  */
817   gcc_assert (base_aligned
818               || (TREE_CODE (base) == VAR_DECL
819                   && DECL_ALIGN (base) >= TYPE_ALIGN (vectype)));
820
821   /* Modulo alignment.  */
822   misalign = size_binop (FLOOR_MOD_EXPR, misalign, alignment);
823
824   if (!host_integerp (misalign, 1))
825     {
826       /* Negative or overflowed misalignment value.  */
827       if (vect_print_dump_info (REPORT_DETAILS))
828         fprintf (vect_dump, "unexpected misalign value");
829       return false;
830     }
831
832   SET_DR_MISALIGNMENT (dr, TREE_INT_CST_LOW (misalign));
833
834   if (vect_print_dump_info (REPORT_DETAILS))
835     {
836       fprintf (vect_dump, "misalign = %d bytes of ref ", DR_MISALIGNMENT (dr));
837       print_generic_expr (vect_dump, ref, TDF_SLIM);
838     }
839
840   return true;
841 }
842
843
844 /* Function vect_compute_data_refs_alignment
845
846    Compute the misalignment of data references in the loop.
847    Return FALSE if a data reference is found that cannot be vectorized.  */
848
849 static bool
850 vect_compute_data_refs_alignment (loop_vec_info loop_vinfo,
851                                   bb_vec_info bb_vinfo)
852 {
853   VEC (data_reference_p, heap) *datarefs;
854   struct data_reference *dr;
855   unsigned int i;
856
857   if (loop_vinfo)
858     datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
859   else
860     datarefs = BB_VINFO_DATAREFS (bb_vinfo);
861
862   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
863     if (STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dr)))
864         && !vect_compute_data_ref_alignment (dr))
865       {
866         if (bb_vinfo)
867           {
868             /* Mark unsupported statement as unvectorizable.  */
869             STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dr))) = false;
870             continue;
871           }
872         else
873           return false;
874       }
875
876   return true;
877 }
878
879
880 /* Function vect_update_misalignment_for_peel
881
882    DR - the data reference whose misalignment is to be adjusted.
883    DR_PEEL - the data reference whose misalignment is being made
884              zero in the vector loop by the peel.
885    NPEEL - the number of iterations in the peel loop if the misalignment
886            of DR_PEEL is known at compile time.  */
887
888 static void
889 vect_update_misalignment_for_peel (struct data_reference *dr,
890                                    struct data_reference *dr_peel, int npeel)
891 {
892   unsigned int i;
893   VEC(dr_p,heap) *same_align_drs;
894   struct data_reference *current_dr;
895   int dr_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr))));
896   int dr_peel_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr_peel))));
897   stmt_vec_info stmt_info = vinfo_for_stmt (DR_STMT (dr));
898   stmt_vec_info peel_stmt_info = vinfo_for_stmt (DR_STMT (dr_peel));
899
900  /* For interleaved data accesses the step in the loop must be multiplied by
901      the size of the interleaving group.  */
902   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
903     dr_size *= DR_GROUP_SIZE (vinfo_for_stmt (DR_GROUP_FIRST_DR (stmt_info)));
904   if (STMT_VINFO_STRIDED_ACCESS (peel_stmt_info))
905     dr_peel_size *= DR_GROUP_SIZE (peel_stmt_info);
906
907   /* It can be assumed that the data refs with the same alignment as dr_peel
908      are aligned in the vector loop.  */
909   same_align_drs
910     = STMT_VINFO_SAME_ALIGN_REFS (vinfo_for_stmt (DR_STMT (dr_peel)));
911   for (i = 0; VEC_iterate (dr_p, same_align_drs, i, current_dr); i++)
912     {
913       if (current_dr != dr)
914         continue;
915       gcc_assert (DR_MISALIGNMENT (dr) / dr_size ==
916                   DR_MISALIGNMENT (dr_peel) / dr_peel_size);
917       SET_DR_MISALIGNMENT (dr, 0);
918       return;
919     }
920
921   if (known_alignment_for_access_p (dr)
922       && known_alignment_for_access_p (dr_peel))
923     {
924       int misal = DR_MISALIGNMENT (dr);
925       tree vectype = STMT_VINFO_VECTYPE (stmt_info);
926       misal += npeel * dr_size;
927       misal %= GET_MODE_SIZE (TYPE_MODE (vectype));
928       SET_DR_MISALIGNMENT (dr, misal);
929       return;
930     }
931
932   if (vect_print_dump_info (REPORT_DETAILS))
933     fprintf (vect_dump, "Setting misalignment to -1.");
934   SET_DR_MISALIGNMENT (dr, -1);
935 }
936
937
938 /* Function vect_verify_datarefs_alignment
939
940    Return TRUE if all data references in the loop can be
941    handled with respect to alignment.  */
942
943 bool
944 vect_verify_datarefs_alignment (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
945 {
946   VEC (data_reference_p, heap) *datarefs;
947   struct data_reference *dr;
948   enum dr_alignment_support supportable_dr_alignment;
949   unsigned int i;
950
951   if (loop_vinfo)
952     datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
953   else
954     datarefs = BB_VINFO_DATAREFS (bb_vinfo);
955
956   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
957     {
958       gimple stmt = DR_STMT (dr);
959       stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
960
961       /* For interleaving, only the alignment of the first access matters. 
962          Skip statements marked as not vectorizable.  */
963       if ((STMT_VINFO_STRIDED_ACCESS (stmt_info)
964            && DR_GROUP_FIRST_DR (stmt_info) != stmt)
965           || !STMT_VINFO_VECTORIZABLE (stmt_info))
966         continue;
967
968       supportable_dr_alignment = vect_supportable_dr_alignment (dr);
969       if (!supportable_dr_alignment)
970         {
971           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
972             {
973               if (DR_IS_READ (dr))
974                 fprintf (vect_dump,
975                          "not vectorized: unsupported unaligned load.");
976               else
977                 fprintf (vect_dump,
978                          "not vectorized: unsupported unaligned store.");
979
980               print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
981             }
982           return false;
983         }
984       if (supportable_dr_alignment != dr_aligned
985           && vect_print_dump_info (REPORT_ALIGNMENT))
986         fprintf (vect_dump, "Vectorizing an unaligned access.");
987     }
988   return true;
989 }
990
991
992 /* Function vector_alignment_reachable_p
993
994    Return true if vector alignment for DR is reachable by peeling
995    a few loop iterations.  Return false otherwise.  */
996
997 static bool
998 vector_alignment_reachable_p (struct data_reference *dr)
999 {
1000   gimple stmt = DR_STMT (dr);
1001   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1002   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
1003
1004   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
1005     {
1006       /* For interleaved access we peel only if number of iterations in
1007          the prolog loop ({VF - misalignment}), is a multiple of the
1008          number of the interleaved accesses.  */
1009       int elem_size, mis_in_elements;
1010       int nelements = TYPE_VECTOR_SUBPARTS (vectype);
1011
1012       /* FORNOW: handle only known alignment.  */
1013       if (!known_alignment_for_access_p (dr))
1014         return false;
1015
1016       elem_size = GET_MODE_SIZE (TYPE_MODE (vectype)) / nelements;
1017       mis_in_elements = DR_MISALIGNMENT (dr) / elem_size;
1018
1019       if ((nelements - mis_in_elements) % DR_GROUP_SIZE (stmt_info))
1020         return false;
1021     }
1022
1023   /* If misalignment is known at the compile time then allow peeling
1024      only if natural alignment is reachable through peeling.  */
1025   if (known_alignment_for_access_p (dr) && !aligned_access_p (dr))
1026     {
1027       HOST_WIDE_INT elmsize =
1028                 int_cst_value (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
1029       if (vect_print_dump_info (REPORT_DETAILS))
1030         {
1031           fprintf (vect_dump, "data size =" HOST_WIDE_INT_PRINT_DEC, elmsize);
1032           fprintf (vect_dump, ". misalignment = %d. ", DR_MISALIGNMENT (dr));
1033         }
1034       if (DR_MISALIGNMENT (dr) % elmsize)
1035         {
1036           if (vect_print_dump_info (REPORT_DETAILS))
1037             fprintf (vect_dump, "data size does not divide the misalignment.\n");
1038           return false;
1039         }
1040     }
1041
1042   if (!known_alignment_for_access_p (dr))
1043     {
1044       tree type = (TREE_TYPE (DR_REF (dr)));
1045       tree ba = DR_BASE_OBJECT (dr);
1046       bool is_packed = false;
1047
1048       if (ba)
1049         is_packed = contains_packed_reference (ba);
1050
1051       if (vect_print_dump_info (REPORT_DETAILS))
1052         fprintf (vect_dump, "Unknown misalignment, is_packed = %d",is_packed);
1053       if (targetm.vectorize.vector_alignment_reachable (type, is_packed))
1054         return true;
1055       else
1056         return false;
1057     }
1058
1059   return true;
1060 }
1061
1062 /* Function vect_enhance_data_refs_alignment
1063
1064    This pass will use loop versioning and loop peeling in order to enhance
1065    the alignment of data references in the loop.
1066
1067    FOR NOW: we assume that whatever versioning/peeling takes place, only the
1068    original loop is to be vectorized; Any other loops that are created by
1069    the transformations performed in this pass - are not supposed to be
1070    vectorized. This restriction will be relaxed.
1071
1072    This pass will require a cost model to guide it whether to apply peeling
1073    or versioning or a combination of the two. For example, the scheme that
1074    intel uses when given a loop with several memory accesses, is as follows:
1075    choose one memory access ('p') which alignment you want to force by doing
1076    peeling. Then, either (1) generate a loop in which 'p' is aligned and all
1077    other accesses are not necessarily aligned, or (2) use loop versioning to
1078    generate one loop in which all accesses are aligned, and another loop in
1079    which only 'p' is necessarily aligned.
1080
1081    ("Automatic Intra-Register Vectorization for the Intel Architecture",
1082    Aart J.C. Bik, Milind Girkar, Paul M. Grey and Ximmin Tian, International
1083    Journal of Parallel Programming, Vol. 30, No. 2, April 2002.)
1084
1085    Devising a cost model is the most critical aspect of this work. It will
1086    guide us on which access to peel for, whether to use loop versioning, how
1087    many versions to create, etc. The cost model will probably consist of
1088    generic considerations as well as target specific considerations (on
1089    powerpc for example, misaligned stores are more painful than misaligned
1090    loads).
1091
1092    Here are the general steps involved in alignment enhancements:
1093
1094      -- original loop, before alignment analysis:
1095         for (i=0; i<N; i++){
1096           x = q[i];                     # DR_MISALIGNMENT(q) = unknown
1097           p[i] = y;                     # DR_MISALIGNMENT(p) = unknown
1098         }
1099
1100      -- After vect_compute_data_refs_alignment:
1101         for (i=0; i<N; i++){
1102           x = q[i];                     # DR_MISALIGNMENT(q) = 3
1103           p[i] = y;                     # DR_MISALIGNMENT(p) = unknown
1104         }
1105
1106      -- Possibility 1: we do loop versioning:
1107      if (p is aligned) {
1108         for (i=0; i<N; i++){    # loop 1A
1109           x = q[i];                     # DR_MISALIGNMENT(q) = 3
1110           p[i] = y;                     # DR_MISALIGNMENT(p) = 0
1111         }
1112      }
1113      else {
1114         for (i=0; i<N; i++){    # loop 1B
1115           x = q[i];                     # DR_MISALIGNMENT(q) = 3
1116           p[i] = y;                     # DR_MISALIGNMENT(p) = unaligned
1117         }
1118      }
1119
1120      -- Possibility 2: we do loop peeling:
1121      for (i = 0; i < 3; i++){   # (scalar loop, not to be vectorized).
1122         x = q[i];
1123         p[i] = y;
1124      }
1125      for (i = 3; i < N; i++){   # loop 2A
1126         x = q[i];                       # DR_MISALIGNMENT(q) = 0
1127         p[i] = y;                       # DR_MISALIGNMENT(p) = unknown
1128      }
1129
1130      -- Possibility 3: combination of loop peeling and versioning:
1131      for (i = 0; i < 3; i++){   # (scalar loop, not to be vectorized).
1132         x = q[i];
1133         p[i] = y;
1134      }
1135      if (p is aligned) {
1136         for (i = 3; i<N; i++){  # loop 3A
1137           x = q[i];                     # DR_MISALIGNMENT(q) = 0
1138           p[i] = y;                     # DR_MISALIGNMENT(p) = 0
1139         }
1140      }
1141      else {
1142         for (i = 3; i<N; i++){  # loop 3B
1143           x = q[i];                     # DR_MISALIGNMENT(q) = 0
1144           p[i] = y;                     # DR_MISALIGNMENT(p) = unaligned
1145         }
1146      }
1147
1148      These loops are later passed to loop_transform to be vectorized. The
1149      vectorizer will use the alignment information to guide the transformation
1150      (whether to generate regular loads/stores, or with special handling for
1151      misalignment).  */
1152
1153 bool
1154 vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
1155 {
1156   VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
1157   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1158   enum dr_alignment_support supportable_dr_alignment;
1159   struct data_reference *dr0 = NULL;
1160   struct data_reference *dr;
1161   unsigned int i;
1162   bool do_peeling = false;
1163   bool do_versioning = false;
1164   bool stat;
1165   gimple stmt;
1166   stmt_vec_info stmt_info;
1167   int vect_versioning_for_alias_required;
1168
1169   if (vect_print_dump_info (REPORT_DETAILS))
1170     fprintf (vect_dump, "=== vect_enhance_data_refs_alignment ===");
1171
1172   /* While cost model enhancements are expected in the future, the high level
1173      view of the code at this time is as follows:
1174
1175      A) If there is a misaligned access then see if peeling to align
1176         this access can make all data references satisfy
1177         vect_supportable_dr_alignment.  If so, update data structures
1178         as needed and return true.
1179
1180      B) If peeling wasn't possible and there is a data reference with an
1181         unknown misalignment that does not satisfy vect_supportable_dr_alignment
1182         then see if loop versioning checks can be used to make all data
1183         references satisfy vect_supportable_dr_alignment.  If so, update
1184         data structures as needed and return true.
1185
1186      C) If neither peeling nor versioning were successful then return false if
1187         any data reference does not satisfy vect_supportable_dr_alignment.
1188
1189      D) Return true (all data references satisfy vect_supportable_dr_alignment).
1190
1191      Note, Possibility 3 above (which is peeling and versioning together) is not
1192      being done at this time.  */
1193
1194   /* (1) Peeling to force alignment.  */
1195
1196   /* (1.1) Decide whether to perform peeling, and how many iterations to peel:
1197      Considerations:
1198      + How many accesses will become aligned due to the peeling
1199      - How many accesses will become unaligned due to the peeling,
1200        and the cost of misaligned accesses.
1201      - The cost of peeling (the extra runtime checks, the increase
1202        in code size).
1203
1204      The scheme we use FORNOW: peel to force the alignment of the first
1205      unsupported misaligned access in the loop.
1206
1207      TODO: Use a cost model.  */
1208
1209   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
1210     {
1211       stmt = DR_STMT (dr);
1212       stmt_info = vinfo_for_stmt (stmt);
1213
1214       /* For interleaving, only the alignment of the first access
1215          matters.  */
1216       if (STMT_VINFO_STRIDED_ACCESS (stmt_info)
1217           && DR_GROUP_FIRST_DR (stmt_info) != stmt)
1218         continue;
1219
1220       if (!DR_IS_READ (dr) && !aligned_access_p (dr))
1221         {
1222           do_peeling = vector_alignment_reachable_p (dr);
1223           if (do_peeling)
1224             dr0 = dr;
1225           if (!do_peeling && vect_print_dump_info (REPORT_DETAILS))
1226             fprintf (vect_dump, "vector alignment may not be reachable");
1227           break;
1228         }
1229     }
1230
1231   vect_versioning_for_alias_required
1232     = LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo);
1233
1234   /* Temporarily, if versioning for alias is required, we disable peeling
1235      until we support peeling and versioning.  Often peeling for alignment
1236      will require peeling for loop-bound, which in turn requires that we
1237      know how to adjust the loop ivs after the loop.  */
1238   if (vect_versioning_for_alias_required
1239       || !vect_can_advance_ivs_p (loop_vinfo)
1240       || !slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
1241     do_peeling = false;
1242
1243   if (do_peeling)
1244     {
1245       int mis;
1246       int npeel = 0;
1247       gimple stmt = DR_STMT (dr0);
1248       stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1249       tree vectype = STMT_VINFO_VECTYPE (stmt_info);
1250       int nelements = TYPE_VECTOR_SUBPARTS (vectype);
1251
1252       if (known_alignment_for_access_p (dr0))
1253         {
1254           /* Since it's known at compile time, compute the number of iterations
1255              in the peeled loop (the peeling factor) for use in updating
1256              DR_MISALIGNMENT values.  The peeling factor is the vectorization
1257              factor minus the misalignment as an element count.  */
1258           mis = DR_MISALIGNMENT (dr0);
1259           mis /= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr0))));
1260           npeel = nelements - mis;
1261
1262           /* For interleaved data access every iteration accesses all the
1263              members of the group, therefore we divide the number of iterations
1264              by the group size.  */
1265           stmt_info = vinfo_for_stmt (DR_STMT (dr0));
1266           if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
1267             npeel /= DR_GROUP_SIZE (stmt_info);
1268
1269           if (vect_print_dump_info (REPORT_DETAILS))
1270             fprintf (vect_dump, "Try peeling by %d", npeel);
1271         }
1272
1273       /* Ensure that all data refs can be vectorized after the peel.  */
1274       for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
1275         {
1276           int save_misalignment;
1277
1278           if (dr == dr0)
1279             continue;
1280
1281           stmt = DR_STMT (dr);
1282           stmt_info = vinfo_for_stmt (stmt);
1283           /* For interleaving, only the alignment of the first access
1284             matters.  */
1285           if (STMT_VINFO_STRIDED_ACCESS (stmt_info)
1286               && DR_GROUP_FIRST_DR (stmt_info) != stmt)
1287             continue;
1288
1289           save_misalignment = DR_MISALIGNMENT (dr);
1290           vect_update_misalignment_for_peel (dr, dr0, npeel);
1291           supportable_dr_alignment = vect_supportable_dr_alignment (dr);
1292           SET_DR_MISALIGNMENT (dr, save_misalignment);
1293
1294           if (!supportable_dr_alignment)
1295             {
1296               do_peeling = false;
1297               break;
1298             }
1299         }
1300
1301       if (do_peeling)
1302         {
1303           /* (1.2) Update the DR_MISALIGNMENT of each data reference DR_i.
1304              If the misalignment of DR_i is identical to that of dr0 then set
1305              DR_MISALIGNMENT (DR_i) to zero.  If the misalignment of DR_i and
1306              dr0 are known at compile time then increment DR_MISALIGNMENT (DR_i)
1307              by the peeling factor times the element size of DR_i (MOD the
1308              vectorization factor times the size).  Otherwise, the
1309              misalignment of DR_i must be set to unknown.  */
1310           for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
1311             if (dr != dr0)
1312               vect_update_misalignment_for_peel (dr, dr0, npeel);
1313
1314           LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0;
1315           LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) = DR_MISALIGNMENT (dr0);
1316           SET_DR_MISALIGNMENT (dr0, 0);
1317           if (vect_print_dump_info (REPORT_ALIGNMENT))
1318             fprintf (vect_dump, "Alignment of access forced using peeling.");
1319
1320           if (vect_print_dump_info (REPORT_DETAILS))
1321             fprintf (vect_dump, "Peeling for alignment will be applied.");
1322
1323           stat = vect_verify_datarefs_alignment (loop_vinfo, NULL);
1324           gcc_assert (stat);
1325           return stat;
1326         }
1327     }
1328
1329
1330   /* (2) Versioning to force alignment.  */
1331
1332   /* Try versioning if:
1333      1) flag_tree_vect_loop_version is TRUE
1334      2) optimize loop for speed
1335      3) there is at least one unsupported misaligned data ref with an unknown
1336         misalignment, and
1337      4) all misaligned data refs with a known misalignment are supported, and
1338      5) the number of runtime alignment checks is within reason.  */
1339
1340   do_versioning =
1341         flag_tree_vect_loop_version
1342         && optimize_loop_nest_for_speed_p (loop)
1343         && (!loop->inner); /* FORNOW */
1344
1345   if (do_versioning)
1346     {
1347       for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
1348         {
1349           stmt = DR_STMT (dr);
1350           stmt_info = vinfo_for_stmt (stmt);
1351
1352           /* For interleaving, only the alignment of the first access
1353              matters.  */
1354           if (aligned_access_p (dr)
1355               || (STMT_VINFO_STRIDED_ACCESS (stmt_info)
1356                   && DR_GROUP_FIRST_DR (stmt_info) != stmt))
1357             continue;
1358
1359           supportable_dr_alignment = vect_supportable_dr_alignment (dr);
1360
1361           if (!supportable_dr_alignment)
1362             {
1363               gimple stmt;
1364               int mask;
1365               tree vectype;
1366
1367               if (known_alignment_for_access_p (dr)
1368                   || VEC_length (gimple,
1369                                  LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
1370                      >= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS))
1371                 {
1372                   do_versioning = false;
1373                   break;
1374                 }
1375
1376               stmt = DR_STMT (dr);
1377               vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
1378               gcc_assert (vectype);
1379
1380               /* The rightmost bits of an aligned address must be zeros.
1381                  Construct the mask needed for this test.  For example,
1382                  GET_MODE_SIZE for the vector mode V4SI is 16 bytes so the
1383                  mask must be 15 = 0xf. */
1384               mask = GET_MODE_SIZE (TYPE_MODE (vectype)) - 1;
1385
1386               /* FORNOW: use the same mask to test all potentially unaligned
1387                  references in the loop.  The vectorizer currently supports
1388                  a single vector size, see the reference to
1389                  GET_MODE_NUNITS (TYPE_MODE (vectype)) where the
1390                  vectorization factor is computed.  */
1391               gcc_assert (!LOOP_VINFO_PTR_MASK (loop_vinfo)
1392                           || LOOP_VINFO_PTR_MASK (loop_vinfo) == mask);
1393               LOOP_VINFO_PTR_MASK (loop_vinfo) = mask;
1394               VEC_safe_push (gimple, heap,
1395                              LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo),
1396                              DR_STMT (dr));
1397             }
1398         }
1399
1400       /* Versioning requires at least one misaligned data reference.  */
1401       if (!LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo))
1402         do_versioning = false;
1403       else if (!do_versioning)
1404         VEC_truncate (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo), 0);
1405     }
1406
1407   if (do_versioning)
1408     {
1409       VEC(gimple,heap) *may_misalign_stmts
1410         = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
1411       gimple stmt;
1412
1413       /* It can now be assumed that the data references in the statements
1414          in LOOP_VINFO_MAY_MISALIGN_STMTS will be aligned in the version
1415          of the loop being vectorized.  */
1416       for (i = 0; VEC_iterate (gimple, may_misalign_stmts, i, stmt); i++)
1417         {
1418           stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1419           dr = STMT_VINFO_DATA_REF (stmt_info);
1420           SET_DR_MISALIGNMENT (dr, 0);
1421           if (vect_print_dump_info (REPORT_ALIGNMENT))
1422             fprintf (vect_dump, "Alignment of access forced using versioning.");
1423         }
1424
1425       if (vect_print_dump_info (REPORT_DETAILS))
1426         fprintf (vect_dump, "Versioning for alignment will be applied.");
1427
1428       /* Peeling and versioning can't be done together at this time.  */
1429       gcc_assert (! (do_peeling && do_versioning));
1430
1431       stat = vect_verify_datarefs_alignment (loop_vinfo, NULL);
1432       gcc_assert (stat);
1433       return stat;
1434     }
1435
1436   /* This point is reached if neither peeling nor versioning is being done.  */
1437   gcc_assert (! (do_peeling || do_versioning));
1438
1439   stat = vect_verify_datarefs_alignment (loop_vinfo, NULL);
1440   return stat;
1441 }
1442
1443
1444 /* Function vect_find_same_alignment_drs.
1445
1446    Update group and alignment relations according to the chosen
1447    vectorization factor.  */
1448
1449 static void
1450 vect_find_same_alignment_drs (struct data_dependence_relation *ddr,
1451                               loop_vec_info loop_vinfo)
1452 {
1453   unsigned int i;
1454   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1455   int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
1456   struct data_reference *dra = DDR_A (ddr);
1457   struct data_reference *drb = DDR_B (ddr);
1458   stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
1459   stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
1460   int dra_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dra))));
1461   int drb_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (drb))));
1462   lambda_vector dist_v;
1463   unsigned int loop_depth;
1464
1465   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
1466     return;
1467
1468   if ((DR_IS_READ (dra) && DR_IS_READ (drb)) || dra == drb)
1469     return;
1470
1471   if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
1472     return;
1473
1474   /* Loop-based vectorization and known data dependence.  */
1475   if (DDR_NUM_DIST_VECTS (ddr) == 0)
1476     return;
1477
1478   loop_depth = index_in_loop_nest (loop->num, DDR_LOOP_NEST (ddr));
1479   for (i = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v); i++)
1480     {
1481       int dist = dist_v[loop_depth];
1482
1483       if (vect_print_dump_info (REPORT_DR_DETAILS))
1484         fprintf (vect_dump, "dependence distance  = %d.", dist);
1485
1486       /* Same loop iteration.  */
1487       if (dist == 0
1488           || (dist % vectorization_factor == 0 && dra_size == drb_size))
1489         {
1490           /* Two references with distance zero have the same alignment.  */
1491           VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_a), drb);
1492           VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_b), dra);
1493           if (vect_print_dump_info (REPORT_ALIGNMENT))
1494             fprintf (vect_dump, "accesses have the same alignment.");
1495           if (vect_print_dump_info (REPORT_DR_DETAILS))
1496             {
1497               fprintf (vect_dump, "dependence distance modulo vf == 0 between ");
1498               print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
1499               fprintf (vect_dump, " and ");
1500               print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
1501             }
1502         }
1503     }
1504 }
1505
1506
1507 /* Function vect_analyze_data_refs_alignment
1508
1509    Analyze the alignment of the data-references in the loop.
1510    Return FALSE if a data reference is found that cannot be vectorized.  */
1511
1512 bool
1513 vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo,
1514                                   bb_vec_info bb_vinfo)
1515 {
1516   if (vect_print_dump_info (REPORT_DETAILS))
1517     fprintf (vect_dump, "=== vect_analyze_data_refs_alignment ===");
1518
1519   /* Mark groups of data references with same alignment using
1520      data dependence information.  */
1521   if (loop_vinfo)
1522     {
1523       VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo);
1524       struct data_dependence_relation *ddr;
1525       unsigned int i;
1526
1527       for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
1528         vect_find_same_alignment_drs (ddr, loop_vinfo);
1529     }
1530
1531   if (!vect_compute_data_refs_alignment (loop_vinfo, bb_vinfo))
1532     {
1533       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1534         fprintf (vect_dump,
1535                  "not vectorized: can't calculate alignment for data ref.");
1536       return false;
1537     }
1538
1539   return true;
1540 }
1541
1542
1543 /* Analyze groups of strided accesses: check that DR belongs to a group of
1544    strided accesses of legal size, step, etc. Detect gaps, single element
1545    interleaving, and other special cases. Set strided access info.
1546    Collect groups of strided stores for further use in SLP analysis.  */
1547
1548 static bool
1549 vect_analyze_group_access (struct data_reference *dr)
1550 {
1551   tree step = DR_STEP (dr);
1552   tree scalar_type = TREE_TYPE (DR_REF (dr));
1553   HOST_WIDE_INT type_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
1554   gimple stmt = DR_STMT (dr);
1555   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1556   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
1557   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
1558   HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
1559   HOST_WIDE_INT stride;
1560   bool slp_impossible = false;
1561
1562   /* For interleaving, STRIDE is STEP counted in elements, i.e., the size of the
1563      interleaving group (including gaps).  */
1564   stride = dr_step / type_size;
1565
1566   /* Not consecutive access is possible only if it is a part of interleaving.  */
1567   if (!DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)))
1568     {
1569       /* Check if it this DR is a part of interleaving, and is a single
1570          element of the group that is accessed in the loop.  */
1571
1572       /* Gaps are supported only for loads. STEP must be a multiple of the type
1573          size.  The size of the group must be a power of 2.  */
1574       if (DR_IS_READ (dr)
1575           && (dr_step % type_size) == 0
1576           && stride > 0
1577           && exact_log2 (stride) != -1)
1578         {
1579           DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) = stmt;
1580           DR_GROUP_SIZE (vinfo_for_stmt (stmt)) = stride;
1581           if (vect_print_dump_info (REPORT_DR_DETAILS))
1582             {
1583               fprintf (vect_dump, "Detected single element interleaving ");
1584               print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
1585               fprintf (vect_dump, " step ");
1586               print_generic_expr (vect_dump, step, TDF_SLIM);
1587             }
1588           return true;
1589         }
1590
1591       if (vect_print_dump_info (REPORT_DETAILS))
1592         {
1593           fprintf (vect_dump, "not consecutive access ");
1594           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
1595         }
1596
1597       if (bb_vinfo)
1598         {
1599           /* Mark the statement as unvectorizable.  */
1600           STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dr))) = false;
1601           return true;
1602         }
1603     
1604       return false;
1605     }
1606
1607   if (DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) == stmt)
1608     {
1609       /* First stmt in the interleaving chain. Check the chain.  */
1610       gimple next = DR_GROUP_NEXT_DR (vinfo_for_stmt (stmt));
1611       struct data_reference *data_ref = dr;
1612       unsigned int count = 1;
1613       tree next_step;
1614       tree prev_init = DR_INIT (data_ref);
1615       gimple prev = stmt;
1616       HOST_WIDE_INT diff, count_in_bytes, gaps = 0;
1617
1618       while (next)
1619         {
1620           /* Skip same data-refs. In case that two or more stmts share data-ref
1621              (supported only for loads), we vectorize only the first stmt, and
1622              the rest get their vectorized loads from the first one.  */
1623           if (!tree_int_cst_compare (DR_INIT (data_ref),
1624                                      DR_INIT (STMT_VINFO_DATA_REF (
1625                                                    vinfo_for_stmt (next)))))
1626             {
1627               if (!DR_IS_READ (data_ref))
1628                 {
1629                   if (vect_print_dump_info (REPORT_DETAILS))
1630                     fprintf (vect_dump, "Two store stmts share the same dr.");
1631                   return false;
1632                 }
1633
1634               /* Check that there is no load-store dependencies for this loads
1635                  to prevent a case of load-store-load to the same location.  */
1636               if (DR_GROUP_READ_WRITE_DEPENDENCE (vinfo_for_stmt (next))
1637                   || DR_GROUP_READ_WRITE_DEPENDENCE (vinfo_for_stmt (prev)))
1638                 {
1639                   if (vect_print_dump_info (REPORT_DETAILS))
1640                     fprintf (vect_dump,
1641                              "READ_WRITE dependence in interleaving.");
1642                   return false;
1643                 }
1644
1645               /* For load use the same data-ref load.  */
1646               DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next)) = prev;
1647
1648               prev = next;
1649               next = DR_GROUP_NEXT_DR (vinfo_for_stmt (next));
1650               continue;
1651             }
1652           prev = next;
1653
1654           /* Check that all the accesses have the same STEP.  */
1655           next_step = DR_STEP (STMT_VINFO_DATA_REF (vinfo_for_stmt (next)));
1656           if (tree_int_cst_compare (step, next_step))
1657             {
1658               if (vect_print_dump_info (REPORT_DETAILS))
1659                 fprintf (vect_dump, "not consecutive access in interleaving");
1660               return false;
1661             }
1662
1663           data_ref = STMT_VINFO_DATA_REF (vinfo_for_stmt (next));
1664           /* Check that the distance between two accesses is equal to the type
1665              size. Otherwise, we have gaps.  */
1666           diff = (TREE_INT_CST_LOW (DR_INIT (data_ref))
1667                   - TREE_INT_CST_LOW (prev_init)) / type_size;
1668           if (diff != 1)
1669             {
1670               /* FORNOW: SLP of accesses with gaps is not supported.  */
1671               slp_impossible = true;
1672               if (!DR_IS_READ (data_ref))
1673                 {
1674                   if (vect_print_dump_info (REPORT_DETAILS))
1675                     fprintf (vect_dump, "interleaved store with gaps");
1676                   return false;
1677                 }
1678
1679               gaps += diff - 1;
1680             }
1681
1682           /* Store the gap from the previous member of the group. If there is no
1683              gap in the access, DR_GROUP_GAP is always 1.  */
1684           DR_GROUP_GAP (vinfo_for_stmt (next)) = diff;
1685
1686           prev_init = DR_INIT (data_ref);
1687           next = DR_GROUP_NEXT_DR (vinfo_for_stmt (next));
1688           /* Count the number of data-refs in the chain.  */
1689           count++;
1690         }
1691
1692       /* COUNT is the number of accesses found, we multiply it by the size of
1693          the type to get COUNT_IN_BYTES.  */
1694       count_in_bytes = type_size * count;
1695
1696       /* Check that the size of the interleaving (including gaps) is not
1697          greater than STEP.  */
1698       if (dr_step && dr_step < count_in_bytes + gaps * type_size)
1699         {
1700           if (vect_print_dump_info (REPORT_DETAILS))
1701             {
1702               fprintf (vect_dump, "interleaving size is greater than step for ");
1703               print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
1704             }
1705           return false;
1706         }
1707
1708       /* Check that the size of the interleaving is equal to STEP for stores,
1709          i.e., that there are no gaps.  */
1710       if (dr_step && dr_step != count_in_bytes)
1711         {
1712           if (DR_IS_READ (dr))
1713             {
1714               slp_impossible = true;
1715               /* There is a gap after the last load in the group. This gap is a
1716                  difference between the stride and the number of elements. When
1717                  there is no gap, this difference should be 0.  */
1718               DR_GROUP_GAP (vinfo_for_stmt (stmt)) = stride - count;
1719             }
1720           else
1721             {
1722               if (vect_print_dump_info (REPORT_DETAILS))
1723                 fprintf (vect_dump, "interleaved store with gaps");
1724               return false;
1725             }
1726         }
1727
1728       /* Check that STEP is a multiple of type size.  */
1729       if (dr_step && (dr_step % type_size) != 0)
1730         {
1731           if (vect_print_dump_info (REPORT_DETAILS))
1732             {
1733               fprintf (vect_dump, "step is not a multiple of type size: step ");
1734               print_generic_expr (vect_dump, step, TDF_SLIM);
1735               fprintf (vect_dump, " size ");
1736               print_generic_expr (vect_dump, TYPE_SIZE_UNIT (scalar_type),
1737                                   TDF_SLIM);
1738             }
1739           return false;
1740         }
1741
1742       /* FORNOW: we handle only interleaving that is a power of 2.
1743          We don't fail here if it may be still possible to vectorize the
1744          group using SLP. If not, the size of the group will be checked in
1745          vect_analyze_operations, and the vectorization will fail.  */
1746       if (exact_log2 (stride) == -1)
1747         {
1748           if (vect_print_dump_info (REPORT_DETAILS))
1749             fprintf (vect_dump, "interleaving is not a power of 2");
1750
1751           if (slp_impossible)
1752             return false;
1753         }
1754
1755       if (stride == 0)
1756         stride = count;
1757
1758       DR_GROUP_SIZE (vinfo_for_stmt (stmt)) = stride;
1759       if (vect_print_dump_info (REPORT_DETAILS))
1760         fprintf (vect_dump, "Detected interleaving of size %d", (int)stride);
1761
1762       /* SLP: create an SLP data structure for every interleaving group of
1763          stores for further analysis in vect_analyse_slp.  */
1764       if (!DR_IS_READ (dr) && !slp_impossible)
1765         {
1766           if (loop_vinfo)
1767             VEC_safe_push (gimple, heap, LOOP_VINFO_STRIDED_STORES (loop_vinfo),
1768                            stmt);
1769           if (bb_vinfo)
1770             VEC_safe_push (gimple, heap, BB_VINFO_STRIDED_STORES (bb_vinfo),
1771                            stmt);
1772         }
1773     }
1774
1775   return true;
1776 }
1777
1778
1779 /* Analyze the access pattern of the data-reference DR.
1780    In case of non-consecutive accesses call vect_analyze_group_access() to
1781    analyze groups of strided accesses.  */
1782
1783 static bool
1784 vect_analyze_data_ref_access (struct data_reference *dr)
1785 {
1786   tree step = DR_STEP (dr);
1787   tree scalar_type = TREE_TYPE (DR_REF (dr));
1788   gimple stmt = DR_STMT (dr);
1789   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1790   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
1791   struct loop *loop = NULL;
1792   HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
1793
1794   if (loop_vinfo)
1795     loop = LOOP_VINFO_LOOP (loop_vinfo);
1796
1797   if (loop_vinfo && !step)
1798     {
1799       if (vect_print_dump_info (REPORT_DETAILS))
1800         fprintf (vect_dump, "bad data-ref access in loop");
1801       return false;
1802     }
1803
1804   /* Don't allow invariant accesses in loops.  */
1805   if (loop_vinfo && dr_step == 0)
1806     return false;
1807
1808   if (loop && nested_in_vect_loop_p (loop, stmt))
1809     {
1810       /* Interleaved accesses are not yet supported within outer-loop
1811         vectorization for references in the inner-loop.  */
1812       DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) = NULL;
1813
1814       /* For the rest of the analysis we use the outer-loop step.  */
1815       step = STMT_VINFO_DR_STEP (stmt_info);
1816       dr_step = TREE_INT_CST_LOW (step);
1817
1818       if (dr_step == 0)
1819         {
1820           if (vect_print_dump_info (REPORT_ALIGNMENT))
1821             fprintf (vect_dump, "zero step in outer loop.");
1822           if (DR_IS_READ (dr))
1823             return true;
1824           else
1825             return false;
1826         }
1827     }
1828
1829   /* Consecutive?  */
1830   if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type)))
1831     {
1832       /* Mark that it is not interleaving.  */
1833       DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) = NULL;
1834       return true;
1835     }
1836
1837   if (loop && nested_in_vect_loop_p (loop, stmt))
1838     {
1839       if (vect_print_dump_info (REPORT_ALIGNMENT))
1840         fprintf (vect_dump, "strided access in outer loop.");
1841       return false;
1842     }
1843
1844   /* Not consecutive access - check if it's a part of interleaving group.  */
1845   return vect_analyze_group_access (dr);
1846 }
1847
1848
1849 /* Function vect_analyze_data_ref_accesses.
1850
1851    Analyze the access pattern of all the data references in the loop.
1852
1853    FORNOW: the only access pattern that is considered vectorizable is a
1854            simple step 1 (consecutive) access.
1855
1856    FORNOW: handle only arrays and pointer accesses.  */
1857
1858 bool
1859 vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
1860 {
1861   unsigned int i;
1862   VEC (data_reference_p, heap) *datarefs;
1863   struct data_reference *dr;
1864
1865   if (vect_print_dump_info (REPORT_DETAILS))
1866     fprintf (vect_dump, "=== vect_analyze_data_ref_accesses ===");
1867
1868   if (loop_vinfo)
1869     datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
1870   else
1871     datarefs = BB_VINFO_DATAREFS (bb_vinfo);
1872
1873   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
1874     if (STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dr))) 
1875         && !vect_analyze_data_ref_access (dr))
1876       {
1877         if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
1878           fprintf (vect_dump, "not vectorized: complicated access pattern.");
1879
1880         if (bb_vinfo)
1881           {
1882             /* Mark the statement as not vectorizable.  */
1883             STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dr))) = false;
1884             continue;
1885           }
1886         else
1887           return false;
1888       }
1889
1890   return true;
1891 }
1892
1893 /* Function vect_prune_runtime_alias_test_list.
1894
1895    Prune a list of ddrs to be tested at run-time by versioning for alias.
1896    Return FALSE if resulting list of ddrs is longer then allowed by
1897    PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS, otherwise return TRUE.  */
1898
1899 bool
1900 vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
1901 {
1902   VEC (ddr_p, heap) * ddrs =
1903     LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
1904   unsigned i, j;
1905
1906   if (vect_print_dump_info (REPORT_DETAILS))
1907     fprintf (vect_dump, "=== vect_prune_runtime_alias_test_list ===");
1908
1909   for (i = 0; i < VEC_length (ddr_p, ddrs); )
1910     {
1911       bool found;
1912       ddr_p ddr_i;
1913
1914       ddr_i = VEC_index (ddr_p, ddrs, i);
1915       found = false;
1916
1917       for (j = 0; j < i; j++)
1918         {
1919           ddr_p ddr_j = VEC_index (ddr_p, ddrs, j);
1920
1921           if (vect_vfa_range_equal (ddr_i, ddr_j))
1922             {
1923               if (vect_print_dump_info (REPORT_DR_DETAILS))
1924                 {
1925                   fprintf (vect_dump, "found equal ranges ");
1926                   print_generic_expr (vect_dump, DR_REF (DDR_A (ddr_i)), TDF_SLIM);
1927                   fprintf (vect_dump, ", ");
1928                   print_generic_expr (vect_dump, DR_REF (DDR_B (ddr_i)), TDF_SLIM);
1929                   fprintf (vect_dump, " and ");
1930                   print_generic_expr (vect_dump, DR_REF (DDR_A (ddr_j)), TDF_SLIM);
1931                   fprintf (vect_dump, ", ");
1932                   print_generic_expr (vect_dump, DR_REF (DDR_B (ddr_j)), TDF_SLIM);
1933                 }
1934               found = true;
1935               break;
1936             }
1937         }
1938
1939       if (found)
1940       {
1941         VEC_ordered_remove (ddr_p, ddrs, i);
1942         continue;
1943       }
1944       i++;
1945     }
1946
1947   if (VEC_length (ddr_p, ddrs) >
1948        (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS))
1949     {
1950       if (vect_print_dump_info (REPORT_DR_DETAILS))
1951         {
1952           fprintf (vect_dump,
1953                    "disable versioning for alias - max number of generated "
1954                    "checks exceeded.");
1955         }
1956
1957       VEC_truncate (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), 0);
1958
1959       return false;
1960     }
1961
1962   return true;
1963 }
1964
1965
1966 /* Function vect_analyze_data_refs.
1967
1968   Find all the data references in the loop or basic block.
1969
1970    The general structure of the analysis of data refs in the vectorizer is as
1971    follows:
1972    1- vect_analyze_data_refs(loop/bb): call
1973       compute_data_dependences_for_loop/bb to find and analyze all data-refs
1974       in the loop/bb and their dependences.
1975    2- vect_analyze_dependences(): apply dependence testing using ddrs.
1976    3- vect_analyze_drs_alignment(): check that ref_stmt.alignment is ok.
1977    4- vect_analyze_drs_access(): check that ref_stmt.step is ok.
1978
1979 */
1980
1981 bool
1982 vect_analyze_data_refs (loop_vec_info loop_vinfo,
1983                         bb_vec_info bb_vinfo,
1984                         int *min_vf)
1985 {
1986   struct loop *loop = NULL;
1987   basic_block bb = NULL;
1988   unsigned int i;
1989   VEC (data_reference_p, heap) *datarefs;
1990   struct data_reference *dr;
1991   tree scalar_type;
1992   bool res;
1993
1994   if (vect_print_dump_info (REPORT_DETAILS))
1995     fprintf (vect_dump, "=== vect_analyze_data_refs ===\n");
1996
1997   if (loop_vinfo)
1998     {
1999       loop = LOOP_VINFO_LOOP (loop_vinfo);
2000       res = compute_data_dependences_for_loop
2001         (loop, true, &LOOP_VINFO_DATAREFS (loop_vinfo),
2002          &LOOP_VINFO_DDRS (loop_vinfo));
2003
2004       if (!res)
2005         {
2006           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2007             fprintf (vect_dump, "not vectorized: loop contains function calls"
2008                      " or data references that cannot be analyzed");
2009           return false;
2010         }
2011
2012       datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
2013     }
2014   else
2015     {
2016       bb = BB_VINFO_BB (bb_vinfo);
2017       res = compute_data_dependences_for_bb (bb, true,
2018                                              &BB_VINFO_DATAREFS (bb_vinfo),
2019                                              &BB_VINFO_DDRS (bb_vinfo));
2020       if (!res)
2021         {
2022           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2023             fprintf (vect_dump, "not vectorized: basic block contains function"
2024                      " calls or data references that cannot be analyzed");
2025           return false;
2026         }
2027
2028       datarefs = BB_VINFO_DATAREFS (bb_vinfo);
2029     }
2030
2031   /* Go through the data-refs, check that the analysis succeeded. Update pointer
2032      from stmt_vec_info struct to DR and vectype.  */
2033
2034   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
2035     {
2036       gimple stmt;
2037       stmt_vec_info stmt_info;
2038       tree base, offset, init;
2039       int vf;
2040
2041       if (!dr || !DR_REF (dr))
2042         {
2043           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2044             fprintf (vect_dump, "not vectorized: unhandled data-ref ");
2045           return false;
2046         }
2047
2048       stmt = DR_STMT (dr);
2049       stmt_info = vinfo_for_stmt (stmt);
2050
2051       /* Check that analysis of the data-ref succeeded.  */
2052       if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr) || !DR_INIT (dr)
2053           || !DR_STEP (dr))
2054         {
2055           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2056             {
2057               fprintf (vect_dump, "not vectorized: data ref analysis failed ");
2058               print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
2059             }
2060
2061           if (bb_vinfo)
2062             {
2063               /* Mark the statement as not vectorizable.  */
2064               STMT_VINFO_VECTORIZABLE (stmt_info) = false;
2065               continue;
2066             }
2067           else
2068             return false;
2069         }
2070
2071       if (TREE_CODE (DR_BASE_ADDRESS (dr)) == INTEGER_CST)
2072         {
2073           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2074             fprintf (vect_dump, "not vectorized: base addr of dr is a "
2075                      "constant");
2076           if (bb_vinfo)
2077             {
2078               /* Mark the statement as not vectorizable.  */
2079               STMT_VINFO_VECTORIZABLE (stmt_info) = false;
2080               continue;
2081             }
2082           else
2083             return false;
2084         }
2085
2086       base = unshare_expr (DR_BASE_ADDRESS (dr));
2087       offset = unshare_expr (DR_OFFSET (dr));
2088       init = unshare_expr (DR_INIT (dr));
2089
2090       /* Update DR field in stmt_vec_info struct.  */
2091
2092       /* If the dataref is in an inner-loop of the loop that is considered for
2093          for vectorization, we also want to analyze the access relative to
2094          the outer-loop (DR contains information only relative to the
2095          inner-most enclosing loop).  We do that by building a reference to the
2096          first location accessed by the inner-loop, and analyze it relative to
2097          the outer-loop.  */
2098       if (loop && nested_in_vect_loop_p (loop, stmt))
2099         {
2100           tree outer_step, outer_base, outer_init;
2101           HOST_WIDE_INT pbitsize, pbitpos;
2102           tree poffset;
2103           enum machine_mode pmode;
2104           int punsignedp, pvolatilep;
2105           affine_iv base_iv, offset_iv;
2106           tree dinit;
2107
2108           /* Build a reference to the first location accessed by the
2109              inner-loop: *(BASE+INIT). (The first location is actually
2110              BASE+INIT+OFFSET, but we add OFFSET separately later).  */
2111           tree inner_base = build_fold_indirect_ref
2112                                 (fold_build2 (POINTER_PLUS_EXPR,
2113                                               TREE_TYPE (base), base,
2114                                               fold_convert (sizetype, init)));
2115
2116           if (vect_print_dump_info (REPORT_DETAILS))
2117             {
2118               fprintf (vect_dump, "analyze in outer-loop: ");
2119               print_generic_expr (vect_dump, inner_base, TDF_SLIM);
2120             }
2121
2122           outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos,
2123                           &poffset, &pmode, &punsignedp, &pvolatilep, false);
2124           gcc_assert (outer_base != NULL_TREE);
2125
2126           if (pbitpos % BITS_PER_UNIT != 0)
2127             {
2128               if (vect_print_dump_info (REPORT_DETAILS))
2129                 fprintf (vect_dump, "failed: bit offset alignment.\n");
2130               return false;
2131             }
2132
2133           outer_base = build_fold_addr_expr (outer_base);
2134           if (!simple_iv (loop, loop_containing_stmt (stmt), outer_base,
2135                           &base_iv, false))
2136             {
2137               if (vect_print_dump_info (REPORT_DETAILS))
2138                 fprintf (vect_dump, "failed: evolution of base is not affine.\n");
2139               return false;
2140             }
2141
2142           if (offset)
2143             {
2144               if (poffset)
2145                 poffset = fold_build2 (PLUS_EXPR, TREE_TYPE (offset), offset,
2146                                        poffset);
2147               else
2148                 poffset = offset;
2149             }
2150
2151           if (!poffset)
2152             {
2153               offset_iv.base = ssize_int (0);
2154               offset_iv.step = ssize_int (0);
2155             }
2156           else if (!simple_iv (loop, loop_containing_stmt (stmt), poffset,
2157                                &offset_iv, false))
2158             {
2159               if (vect_print_dump_info (REPORT_DETAILS))
2160                 fprintf (vect_dump, "evolution of offset is not affine.\n");
2161               return false;
2162             }
2163
2164           outer_init = ssize_int (pbitpos / BITS_PER_UNIT);
2165           split_constant_offset (base_iv.base, &base_iv.base, &dinit);
2166           outer_init =  size_binop (PLUS_EXPR, outer_init, dinit);
2167           split_constant_offset (offset_iv.base, &offset_iv.base, &dinit);
2168           outer_init =  size_binop (PLUS_EXPR, outer_init, dinit);
2169
2170           outer_step = size_binop (PLUS_EXPR,
2171                                 fold_convert (ssizetype, base_iv.step),
2172                                 fold_convert (ssizetype, offset_iv.step));
2173
2174           STMT_VINFO_DR_STEP (stmt_info) = outer_step;
2175           /* FIXME: Use canonicalize_base_object_address (base_iv.base); */
2176           STMT_VINFO_DR_BASE_ADDRESS (stmt_info) = base_iv.base;
2177           STMT_VINFO_DR_INIT (stmt_info) = outer_init;
2178           STMT_VINFO_DR_OFFSET (stmt_info) =
2179                                 fold_convert (ssizetype, offset_iv.base);
2180           STMT_VINFO_DR_ALIGNED_TO (stmt_info) =
2181                                 size_int (highest_pow2_factor (offset_iv.base));
2182
2183           if (vect_print_dump_info (REPORT_DETAILS))
2184             {
2185               fprintf (vect_dump, "\touter base_address: ");
2186               print_generic_expr (vect_dump, STMT_VINFO_DR_BASE_ADDRESS (stmt_info), TDF_SLIM);
2187               fprintf (vect_dump, "\n\touter offset from base address: ");
2188               print_generic_expr (vect_dump, STMT_VINFO_DR_OFFSET (stmt_info), TDF_SLIM);
2189               fprintf (vect_dump, "\n\touter constant offset from base address: ");
2190               print_generic_expr (vect_dump, STMT_VINFO_DR_INIT (stmt_info), TDF_SLIM);
2191               fprintf (vect_dump, "\n\touter step: ");
2192               print_generic_expr (vect_dump, STMT_VINFO_DR_STEP (stmt_info), TDF_SLIM);
2193               fprintf (vect_dump, "\n\touter aligned to: ");
2194               print_generic_expr (vect_dump, STMT_VINFO_DR_ALIGNED_TO (stmt_info), TDF_SLIM);
2195             }
2196         }
2197
2198       if (STMT_VINFO_DATA_REF (stmt_info))
2199         {
2200           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2201             {
2202               fprintf (vect_dump,
2203                        "not vectorized: more than one data ref in stmt: ");
2204               print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
2205             }
2206           return false;
2207         }
2208
2209       STMT_VINFO_DATA_REF (stmt_info) = dr;
2210
2211       /* Set vectype for STMT.  */
2212       scalar_type = TREE_TYPE (DR_REF (dr));
2213       STMT_VINFO_VECTYPE (stmt_info) =
2214                 get_vectype_for_scalar_type (scalar_type);
2215       if (!STMT_VINFO_VECTYPE (stmt_info))
2216         {
2217           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
2218             {
2219               fprintf (vect_dump,
2220                        "not vectorized: no vectype for stmt: ");
2221               print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
2222               fprintf (vect_dump, " scalar_type: ");
2223               print_generic_expr (vect_dump, scalar_type, TDF_DETAILS);
2224             }
2225
2226           if (bb_vinfo)
2227             {
2228               /* Mark the statement as not vectorizable.  */
2229               STMT_VINFO_VECTORIZABLE (stmt_info) = false;
2230               continue;
2231             }
2232           else
2233             return false;
2234         }
2235
2236       /* Adjust the minimal vectorization factor according to the
2237          vector type.  */
2238       vf = TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info));
2239       if (vf > *min_vf)
2240         *min_vf = vf;
2241     }
2242
2243   return true;
2244 }
2245
2246
2247 /* Function vect_get_new_vect_var.
2248
2249    Returns a name for a new variable. The current naming scheme appends the
2250    prefix "vect_" or "vect_p" (depending on the value of VAR_KIND) to
2251    the name of vectorizer generated variables, and appends that to NAME if
2252    provided.  */
2253
2254 tree
2255 vect_get_new_vect_var (tree type, enum vect_var_kind var_kind, const char *name)
2256 {
2257   const char *prefix;
2258   tree new_vect_var;
2259
2260   switch (var_kind)
2261   {
2262   case vect_simple_var:
2263     prefix = "vect_";
2264     break;
2265   case vect_scalar_var:
2266     prefix = "stmp_";
2267     break;
2268   case vect_pointer_var:
2269     prefix = "vect_p";
2270     break;
2271   default:
2272     gcc_unreachable ();
2273   }
2274
2275   if (name)
2276     {
2277       char* tmp = concat (prefix, name, NULL);
2278       new_vect_var = create_tmp_var (type, tmp);
2279       free (tmp);
2280     }
2281   else
2282     new_vect_var = create_tmp_var (type, prefix);
2283
2284   /* Mark vector typed variable as a gimple register variable.  */
2285   if (TREE_CODE (type) == VECTOR_TYPE)
2286     DECL_GIMPLE_REG_P (new_vect_var) = true;
2287
2288   return new_vect_var;
2289 }
2290
2291
2292 /* Function vect_create_addr_base_for_vector_ref.
2293
2294    Create an expression that computes the address of the first memory location
2295    that will be accessed for a data reference.
2296
2297    Input:
2298    STMT: The statement containing the data reference.
2299    NEW_STMT_LIST: Must be initialized to NULL_TREE or a statement list.
2300    OFFSET: Optional. If supplied, it is be added to the initial address.
2301    LOOP:    Specify relative to which loop-nest should the address be computed.
2302             For example, when the dataref is in an inner-loop nested in an
2303             outer-loop that is now being vectorized, LOOP can be either the
2304             outer-loop, or the inner-loop. The first memory location accessed
2305             by the following dataref ('in' points to short):
2306
2307                 for (i=0; i<N; i++)
2308                    for (j=0; j<M; j++)
2309                      s += in[i+j]
2310
2311             is as follows:
2312             if LOOP=i_loop:     &in             (relative to i_loop)
2313             if LOOP=j_loop:     &in+i*2B        (relative to j_loop)
2314
2315    Output:
2316    1. Return an SSA_NAME whose value is the address of the memory location of
2317       the first vector of the data reference.
2318    2. If new_stmt_list is not NULL_TREE after return then the caller must insert
2319       these statement(s) which define the returned SSA_NAME.
2320
2321    FORNOW: We are only handling array accesses with step 1.  */
2322
2323 tree
2324 vect_create_addr_base_for_vector_ref (gimple stmt,
2325                                       gimple_seq *new_stmt_list,
2326                                       tree offset,
2327                                       struct loop *loop)
2328 {
2329   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2330   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
2331   tree data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
2332   tree base_name;
2333   tree data_ref_base_var;
2334   tree vec_stmt;
2335   tree addr_base, addr_expr;
2336   tree dest;
2337   gimple_seq seq = NULL;
2338   tree base_offset = unshare_expr (DR_OFFSET (dr));
2339   tree init = unshare_expr (DR_INIT (dr));
2340   tree vect_ptr_type;
2341   tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
2342   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2343
2344   if (loop_vinfo && loop && loop != (gimple_bb (stmt))->loop_father)
2345     {
2346       struct loop *outer_loop = LOOP_VINFO_LOOP (loop_vinfo);
2347
2348       gcc_assert (nested_in_vect_loop_p (outer_loop, stmt));
2349
2350       data_ref_base = unshare_expr (STMT_VINFO_DR_BASE_ADDRESS (stmt_info));
2351       base_offset = unshare_expr (STMT_VINFO_DR_OFFSET (stmt_info));
2352       init = unshare_expr (STMT_VINFO_DR_INIT (stmt_info));
2353     }
2354
2355   if (loop_vinfo)
2356     base_name = build_fold_indirect_ref (data_ref_base);
2357   else
2358     {
2359       base_offset = ssize_int (0);
2360       init = ssize_int (0);
2361       base_name = build_fold_indirect_ref (unshare_expr (DR_REF (dr)));
2362     }
2363
2364   data_ref_base_var = create_tmp_var (TREE_TYPE (data_ref_base), "batmp");
2365   add_referenced_var (data_ref_base_var);
2366   data_ref_base = force_gimple_operand (data_ref_base, &seq, true,
2367                                         data_ref_base_var);
2368   gimple_seq_add_seq (new_stmt_list, seq);
2369
2370   /* Create base_offset */
2371   base_offset = size_binop (PLUS_EXPR,
2372                             fold_convert (sizetype, base_offset),
2373                             fold_convert (sizetype, init));
2374   dest = create_tmp_var (sizetype, "base_off");
2375   add_referenced_var (dest);
2376   base_offset = force_gimple_operand (base_offset, &seq, true, dest);
2377   gimple_seq_add_seq (new_stmt_list, seq);
2378
2379   if (offset)
2380     {
2381       tree tmp = create_tmp_var (sizetype, "offset");
2382
2383       add_referenced_var (tmp);
2384       offset = fold_build2 (MULT_EXPR, sizetype,
2385                             fold_convert (sizetype, offset), step);
2386       base_offset = fold_build2 (PLUS_EXPR, sizetype,
2387                                  base_offset, offset);
2388       base_offset = force_gimple_operand (base_offset, &seq, false, tmp);
2389       gimple_seq_add_seq (new_stmt_list, seq);
2390     }
2391
2392   /* base + base_offset */
2393   if (loop_vinfo)
2394     addr_base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (data_ref_base),
2395                              data_ref_base, base_offset);
2396   else
2397     {
2398       if (TREE_CODE (DR_REF (dr)) == INDIRECT_REF)
2399         addr_base = unshare_expr (TREE_OPERAND (DR_REF (dr), 0));
2400       else
2401         addr_base = build1 (ADDR_EXPR,
2402                             build_pointer_type (TREE_TYPE (DR_REF (dr))),
2403                             unshare_expr (DR_REF (dr)));
2404     }
2405
2406   vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
2407
2408   vec_stmt = fold_convert (vect_ptr_type, addr_base);
2409   addr_expr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
2410                                      get_name (base_name));
2411   add_referenced_var (addr_expr);
2412   vec_stmt = force_gimple_operand (vec_stmt, &seq, false, addr_expr);
2413   gimple_seq_add_seq (new_stmt_list, seq);
2414
2415   if (vect_print_dump_info (REPORT_DETAILS))
2416     {
2417       fprintf (vect_dump, "created ");
2418       print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
2419     }
2420
2421   return vec_stmt;
2422 }
2423
2424
2425 /* Function vect_create_data_ref_ptr.
2426
2427    Create a new pointer to vector type (vp), that points to the first location
2428    accessed in the loop by STMT, along with the def-use update chain to
2429    appropriately advance the pointer through the loop iterations. Also set
2430    aliasing information for the pointer.  This vector pointer is used by the
2431    callers to this function to create a memory reference expression for vector
2432    load/store access.
2433
2434    Input:
2435    1. STMT: a stmt that references memory. Expected to be of the form
2436          GIMPLE_ASSIGN <name, data-ref> or
2437          GIMPLE_ASSIGN <data-ref, name>.
2438    2. AT_LOOP: the loop where the vector memref is to be created.
2439    3. OFFSET (optional): an offset to be added to the initial address accessed
2440         by the data-ref in STMT.
2441    4. ONLY_INIT: indicate if vp is to be updated in the loop, or remain
2442         pointing to the initial address.
2443    5. TYPE: if not NULL indicates the required type of the data-ref.
2444
2445    Output:
2446    1. Declare a new ptr to vector_type, and have it point to the base of the
2447       data reference (initial addressed accessed by the data reference).
2448       For example, for vector of type V8HI, the following code is generated:
2449
2450       v8hi *vp;
2451       vp = (v8hi *)initial_address;
2452
2453       if OFFSET is not supplied:
2454          initial_address = &a[init];
2455       if OFFSET is supplied:
2456          initial_address = &a[init + OFFSET];
2457
2458       Return the initial_address in INITIAL_ADDRESS.
2459
2460    2. If ONLY_INIT is true, just return the initial pointer.  Otherwise, also
2461       update the pointer in each iteration of the loop.
2462
2463       Return the increment stmt that updates the pointer in PTR_INCR.
2464
2465    3. Set INV_P to true if the access pattern of the data reference in the
2466       vectorized loop is invariant. Set it to false otherwise.
2467
2468    4. Return the pointer.  */
2469
2470 tree
2471 vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
2472                           tree offset, tree *initial_address, gimple *ptr_incr,
2473                           bool only_init, bool *inv_p)
2474 {
2475   tree base_name;
2476   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2477   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2478   struct loop *loop = NULL;
2479   bool nested_in_vect_loop = false;
2480   struct loop *containing_loop = NULL;
2481   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
2482   tree vect_ptr_type;
2483   tree vect_ptr;
2484   tree new_temp;
2485   gimple vec_stmt;
2486   gimple_seq new_stmt_list = NULL;
2487   edge pe = NULL;
2488   basic_block new_bb;
2489   tree vect_ptr_init;
2490   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
2491   tree vptr;
2492   gimple_stmt_iterator incr_gsi;
2493   bool insert_after;
2494   tree indx_before_incr, indx_after_incr;
2495   gimple incr;
2496   tree step;
2497   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
2498   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
2499
2500   if (loop_vinfo)
2501     {
2502       loop = LOOP_VINFO_LOOP (loop_vinfo);
2503       nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
2504       containing_loop = (gimple_bb (stmt))->loop_father;
2505       pe = loop_preheader_edge (loop);
2506     }
2507   else
2508     {
2509       gcc_assert (bb_vinfo);
2510       only_init = true;
2511       *ptr_incr = NULL;
2512     }
2513
2514   /* Check the step (evolution) of the load in LOOP, and record
2515      whether it's invariant.  */
2516   if (nested_in_vect_loop)
2517     step = STMT_VINFO_DR_STEP (stmt_info);
2518   else
2519     step = DR_STEP (STMT_VINFO_DATA_REF (stmt_info));
2520
2521   if (tree_int_cst_compare (step, size_zero_node) == 0)
2522     *inv_p = true;
2523   else
2524     *inv_p = false;
2525
2526   /* Create an expression for the first address accessed by this load
2527      in LOOP.  */
2528   base_name = build_fold_indirect_ref (unshare_expr (DR_BASE_ADDRESS (dr)));
2529
2530   if (vect_print_dump_info (REPORT_DETAILS))
2531     {
2532       tree data_ref_base = base_name;
2533       fprintf (vect_dump, "create vector-pointer variable to type: ");
2534       print_generic_expr (vect_dump, vectype, TDF_SLIM);
2535       if (TREE_CODE (data_ref_base) == VAR_DECL
2536           || TREE_CODE (data_ref_base) == ARRAY_REF)
2537         fprintf (vect_dump, "  vectorizing an array ref: ");
2538       else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
2539         fprintf (vect_dump, "  vectorizing a record based array ref: ");
2540       else if (TREE_CODE (data_ref_base) == SSA_NAME)
2541         fprintf (vect_dump, "  vectorizing a pointer ref: ");
2542       print_generic_expr (vect_dump, base_name, TDF_SLIM);
2543     }
2544
2545   /** (1) Create the new vector-pointer variable:  **/
2546   vect_ptr_type = build_pointer_type (vectype);
2547   vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
2548                                     get_name (base_name));
2549
2550   /* Vector types inherit the alias set of their component type by default so
2551      we need to use a ref-all pointer if the data reference does not conflict
2552      with the created vector data reference because it is not addressable.  */
2553   if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
2554                               get_alias_set (DR_REF (dr))))
2555     {
2556       vect_ptr_type
2557         = build_pointer_type_for_mode (vectype,
2558                                        TYPE_MODE (vect_ptr_type), true);
2559       vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
2560                                         get_name (base_name));
2561     }
2562
2563   /* Likewise for any of the data references in the stmt group.  */
2564   else if (STMT_VINFO_DR_GROUP_SIZE (stmt_info) > 1)
2565     {
2566       gimple orig_stmt = STMT_VINFO_DR_GROUP_FIRST_DR (stmt_info);
2567       do
2568         {
2569           tree lhs = gimple_assign_lhs (orig_stmt);
2570           if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
2571                                       get_alias_set (lhs)))
2572             {
2573               vect_ptr_type
2574                 = build_pointer_type_for_mode (vectype,
2575                                                TYPE_MODE (vect_ptr_type), true);
2576               vect_ptr
2577                 = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
2578                                          get_name (base_name));
2579               break;
2580             }
2581
2582           orig_stmt = STMT_VINFO_DR_GROUP_NEXT_DR (vinfo_for_stmt (orig_stmt));
2583         }
2584       while (orig_stmt);
2585     }
2586
2587   add_referenced_var (vect_ptr);
2588
2589   /** Note: If the dataref is in an inner-loop nested in LOOP, and we are
2590       vectorizing LOOP (i.e. outer-loop vectorization), we need to create two
2591       def-use update cycles for the pointer: One relative to the outer-loop
2592       (LOOP), which is what steps (3) and (4) below do. The other is relative
2593       to the inner-loop (which is the inner-most loop containing the dataref),
2594       and this is done be step (5) below.
2595
2596       When vectorizing inner-most loops, the vectorized loop (LOOP) is also the
2597       inner-most loop, and so steps (3),(4) work the same, and step (5) is
2598       redundant.  Steps (3),(4) create the following:
2599
2600         vp0 = &base_addr;
2601         LOOP:   vp1 = phi(vp0,vp2)
2602                 ...
2603                 ...
2604                 vp2 = vp1 + step
2605                 goto LOOP
2606
2607       If there is an inner-loop nested in loop, then step (5) will also be
2608       applied, and an additional update in the inner-loop will be created:
2609
2610         vp0 = &base_addr;
2611         LOOP:   vp1 = phi(vp0,vp2)
2612                 ...
2613         inner:     vp3 = phi(vp1,vp4)
2614                    vp4 = vp3 + inner_step
2615                    if () goto inner
2616                 ...
2617                 vp2 = vp1 + step
2618                 if () goto LOOP   */
2619
2620   /** (3) Calculate the initial address the vector-pointer, and set
2621           the vector-pointer to point to it before the loop:  **/
2622
2623   /* Create: (&(base[init_val+offset]) in the loop preheader.  */
2624
2625   new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
2626                                                    offset, loop);
2627   if (new_stmt_list)
2628     {
2629       if (pe)
2630         {
2631           new_bb = gsi_insert_seq_on_edge_immediate (pe, new_stmt_list);
2632           gcc_assert (!new_bb);
2633         }
2634       else
2635         gsi_insert_seq_before (&gsi, new_stmt_list, GSI_SAME_STMT);
2636     }
2637
2638   *initial_address = new_temp;
2639
2640   /* Create: p = (vectype *) initial_base  */
2641   vec_stmt = gimple_build_assign (vect_ptr,
2642                                   fold_convert (vect_ptr_type, new_temp));
2643   vect_ptr_init = make_ssa_name (vect_ptr, vec_stmt);
2644   gimple_assign_set_lhs (vec_stmt, vect_ptr_init);
2645   if (pe)
2646     {
2647       new_bb = gsi_insert_on_edge_immediate (pe, vec_stmt);
2648       gcc_assert (!new_bb);
2649     }
2650   else
2651     gsi_insert_before (&gsi, vec_stmt, GSI_SAME_STMT);
2652
2653   /** (4) Handle the updating of the vector-pointer inside the loop.
2654           This is needed when ONLY_INIT is false, and also when AT_LOOP
2655           is the inner-loop nested in LOOP (during outer-loop vectorization).
2656    **/
2657
2658   /* No update in loop is required.  */
2659   if (only_init && (!loop_vinfo || at_loop == loop))
2660     {
2661       /* Copy the points-to information if it exists. */
2662       if (DR_PTR_INFO (dr))
2663         duplicate_ssa_name_ptr_info (vect_ptr_init, DR_PTR_INFO (dr));
2664       vptr = vect_ptr_init;
2665     }
2666   else
2667     {
2668       /* The step of the vector pointer is the Vector Size.  */
2669       tree step = TYPE_SIZE_UNIT (vectype);
2670       /* One exception to the above is when the scalar step of the load in
2671          LOOP is zero. In this case the step here is also zero.  */
2672       if (*inv_p)
2673         step = size_zero_node;
2674
2675       standard_iv_increment_position (loop, &incr_gsi, &insert_after);
2676
2677       create_iv (vect_ptr_init,
2678                  fold_convert (vect_ptr_type, step),
2679                  vect_ptr, loop, &incr_gsi, insert_after,
2680                  &indx_before_incr, &indx_after_incr);
2681       incr = gsi_stmt (incr_gsi);
2682       set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo, NULL));
2683
2684       /* Copy the points-to information if it exists. */
2685       if (DR_PTR_INFO (dr))
2686         {
2687           duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
2688           duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
2689         }
2690       if (ptr_incr)
2691         *ptr_incr = incr;
2692
2693       vptr = indx_before_incr;
2694     }
2695
2696   if (!nested_in_vect_loop || only_init)
2697     return vptr;
2698
2699
2700   /** (5) Handle the updating of the vector-pointer inside the inner-loop
2701           nested in LOOP, if exists: **/
2702
2703   gcc_assert (nested_in_vect_loop);
2704   if (!only_init)
2705     {
2706       standard_iv_increment_position (containing_loop, &incr_gsi,
2707                                       &insert_after);
2708       create_iv (vptr, fold_convert (vect_ptr_type, DR_STEP (dr)), vect_ptr,
2709                  containing_loop, &incr_gsi, insert_after, &indx_before_incr,
2710                  &indx_after_incr);
2711       incr = gsi_stmt (incr_gsi);
2712       set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo, NULL));
2713
2714       /* Copy the points-to information if it exists. */
2715       if (DR_PTR_INFO (dr))
2716         {
2717           duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
2718           duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
2719         }
2720       if (ptr_incr)
2721         *ptr_incr = incr;
2722
2723       return indx_before_incr;
2724     }
2725   else
2726     gcc_unreachable ();
2727 }
2728
2729
2730 /* Function bump_vector_ptr
2731
2732    Increment a pointer (to a vector type) by vector-size. If requested,
2733    i.e. if PTR-INCR is given, then also connect the new increment stmt
2734    to the existing def-use update-chain of the pointer, by modifying
2735    the PTR_INCR as illustrated below:
2736
2737    The pointer def-use update-chain before this function:
2738                         DATAREF_PTR = phi (p_0, p_2)
2739                         ....
2740         PTR_INCR:       p_2 = DATAREF_PTR + step
2741
2742    The pointer def-use update-chain after this function:
2743                         DATAREF_PTR = phi (p_0, p_2)
2744                         ....
2745                         NEW_DATAREF_PTR = DATAREF_PTR + BUMP
2746                         ....
2747         PTR_INCR:       p_2 = NEW_DATAREF_PTR + step
2748
2749    Input:
2750    DATAREF_PTR - ssa_name of a pointer (to vector type) that is being updated
2751                  in the loop.
2752    PTR_INCR - optional. The stmt that updates the pointer in each iteration of
2753               the loop.  The increment amount across iterations is expected
2754               to be vector_size.
2755    BSI - location where the new update stmt is to be placed.
2756    STMT - the original scalar memory-access stmt that is being vectorized.
2757    BUMP - optional. The offset by which to bump the pointer. If not given,
2758           the offset is assumed to be vector_size.
2759
2760    Output: Return NEW_DATAREF_PTR as illustrated above.
2761
2762 */
2763
2764 tree
2765 bump_vector_ptr (tree dataref_ptr, gimple ptr_incr, gimple_stmt_iterator *gsi,
2766                  gimple stmt, tree bump)
2767 {
2768   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2769   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
2770   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
2771   tree ptr_var = SSA_NAME_VAR (dataref_ptr);
2772   tree update = TYPE_SIZE_UNIT (vectype);
2773   gimple incr_stmt;
2774   ssa_op_iter iter;
2775   use_operand_p use_p;
2776   tree new_dataref_ptr;
2777
2778   if (bump)
2779     update = bump;
2780
2781   incr_stmt = gimple_build_assign_with_ops (POINTER_PLUS_EXPR, ptr_var,
2782                                             dataref_ptr, update);
2783   new_dataref_ptr = make_ssa_name (ptr_var, incr_stmt);
2784   gimple_assign_set_lhs (incr_stmt, new_dataref_ptr);
2785   vect_finish_stmt_generation (stmt, incr_stmt, gsi);
2786
2787   /* Copy the points-to information if it exists. */
2788   if (DR_PTR_INFO (dr))
2789     duplicate_ssa_name_ptr_info (new_dataref_ptr, DR_PTR_INFO (dr));
2790
2791   if (!ptr_incr)
2792     return new_dataref_ptr;
2793
2794   /* Update the vector-pointer's cross-iteration increment.  */
2795   FOR_EACH_SSA_USE_OPERAND (use_p, ptr_incr, iter, SSA_OP_USE)
2796     {
2797       tree use = USE_FROM_PTR (use_p);
2798
2799       if (use == dataref_ptr)
2800         SET_USE (use_p, new_dataref_ptr);
2801       else
2802         gcc_assert (tree_int_cst_compare (use, update) == 0);
2803     }
2804
2805   return new_dataref_ptr;
2806 }
2807
2808
2809 /* Function vect_create_destination_var.
2810
2811    Create a new temporary of type VECTYPE.  */
2812
2813 tree
2814 vect_create_destination_var (tree scalar_dest, tree vectype)
2815 {
2816   tree vec_dest;
2817   const char *new_name;
2818   tree type;
2819   enum vect_var_kind kind;
2820
2821   kind = vectype ? vect_simple_var : vect_scalar_var;
2822   type = vectype ? vectype : TREE_TYPE (scalar_dest);
2823
2824   gcc_assert (TREE_CODE (scalar_dest) == SSA_NAME);
2825
2826   new_name = get_name (scalar_dest);
2827   if (!new_name)
2828     new_name = "var_";
2829   vec_dest = vect_get_new_vect_var (type, kind, new_name);
2830   add_referenced_var (vec_dest);
2831
2832   return vec_dest;
2833 }
2834
2835 /* Function vect_strided_store_supported.
2836
2837    Returns TRUE is INTERLEAVE_HIGH and INTERLEAVE_LOW operations are supported,
2838    and FALSE otherwise.  */
2839
2840 bool
2841 vect_strided_store_supported (tree vectype)
2842 {
2843   optab interleave_high_optab, interleave_low_optab;
2844   int mode;
2845
2846   mode = (int) TYPE_MODE (vectype);
2847
2848   /* Check that the operation is supported.  */
2849   interleave_high_optab = optab_for_tree_code (VEC_INTERLEAVE_HIGH_EXPR,
2850                                                vectype, optab_default);
2851   interleave_low_optab = optab_for_tree_code (VEC_INTERLEAVE_LOW_EXPR,
2852                                               vectype, optab_default);
2853   if (!interleave_high_optab || !interleave_low_optab)
2854     {
2855       if (vect_print_dump_info (REPORT_DETAILS))
2856         fprintf (vect_dump, "no optab for interleave.");
2857       return false;
2858     }
2859
2860   if (optab_handler (interleave_high_optab, mode)->insn_code
2861       == CODE_FOR_nothing
2862       || optab_handler (interleave_low_optab, mode)->insn_code
2863       == CODE_FOR_nothing)
2864     {
2865       if (vect_print_dump_info (REPORT_DETAILS))
2866         fprintf (vect_dump, "interleave op not supported by target.");
2867       return false;
2868     }
2869
2870   return true;
2871 }
2872
2873
2874 /* Function vect_permute_store_chain.
2875
2876    Given a chain of interleaved stores in DR_CHAIN of LENGTH that must be
2877    a power of 2, generate interleave_high/low stmts to reorder the data
2878    correctly for the stores. Return the final references for stores in
2879    RESULT_CHAIN.
2880
2881    E.g., LENGTH is 4 and the scalar type is short, i.e., VF is 8.
2882    The input is 4 vectors each containing 8 elements. We assign a number to each
2883    element, the input sequence is:
2884
2885    1st vec:   0  1  2  3  4  5  6  7
2886    2nd vec:   8  9 10 11 12 13 14 15
2887    3rd vec:  16 17 18 19 20 21 22 23
2888    4th vec:  24 25 26 27 28 29 30 31
2889
2890    The output sequence should be:
2891
2892    1st vec:  0  8 16 24  1  9 17 25
2893    2nd vec:  2 10 18 26  3 11 19 27
2894    3rd vec:  4 12 20 28  5 13 21 30
2895    4th vec:  6 14 22 30  7 15 23 31
2896
2897    i.e., we interleave the contents of the four vectors in their order.
2898
2899    We use interleave_high/low instructions to create such output. The input of
2900    each interleave_high/low operation is two vectors:
2901    1st vec    2nd vec
2902    0 1 2 3    4 5 6 7
2903    the even elements of the result vector are obtained left-to-right from the
2904    high/low elements of the first vector. The odd elements of the result are
2905    obtained left-to-right from the high/low elements of the second vector.
2906    The output of interleave_high will be:   0 4 1 5
2907    and of interleave_low:                   2 6 3 7
2908
2909
2910    The permutation is done in log LENGTH stages. In each stage interleave_high
2911    and interleave_low stmts are created for each pair of vectors in DR_CHAIN,
2912    where the first argument is taken from the first half of DR_CHAIN and the
2913    second argument from it's second half.
2914    In our example,
2915
2916    I1: interleave_high (1st vec, 3rd vec)
2917    I2: interleave_low (1st vec, 3rd vec)
2918    I3: interleave_high (2nd vec, 4th vec)
2919    I4: interleave_low (2nd vec, 4th vec)
2920
2921    The output for the first stage is:
2922
2923    I1:  0 16  1 17  2 18  3 19
2924    I2:  4 20  5 21  6 22  7 23
2925    I3:  8 24  9 25 10 26 11 27
2926    I4: 12 28 13 29 14 30 15 31
2927
2928    The output of the second stage, i.e. the final result is:
2929
2930    I1:  0  8 16 24  1  9 17 25
2931    I2:  2 10 18 26  3 11 19 27
2932    I3:  4 12 20 28  5 13 21 30
2933    I4:  6 14 22 30  7 15 23 31.  */
2934
2935 bool
2936 vect_permute_store_chain (VEC(tree,heap) *dr_chain,
2937                           unsigned int length,
2938                           gimple stmt,
2939                           gimple_stmt_iterator *gsi,
2940                           VEC(tree,heap) **result_chain)
2941 {
2942   tree perm_dest, vect1, vect2, high, low;
2943   gimple perm_stmt;
2944   tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
2945   int i;
2946   unsigned int j;
2947   enum tree_code high_code, low_code;
2948
2949   /* Check that the operation is supported.  */
2950   if (!vect_strided_store_supported (vectype))
2951     return false;
2952
2953   *result_chain = VEC_copy (tree, heap, dr_chain);
2954
2955   for (i = 0; i < exact_log2 (length); i++)
2956     {
2957       for (j = 0; j < length/2; j++)
2958         {
2959           vect1 = VEC_index (tree, dr_chain, j);
2960           vect2 = VEC_index (tree, dr_chain, j+length/2);
2961
2962           /* Create interleaving stmt:
2963              in the case of big endian:
2964                                 high = interleave_high (vect1, vect2)
2965              and in the case of little endian:
2966                                 high = interleave_low (vect1, vect2).  */
2967           perm_dest = create_tmp_var (vectype, "vect_inter_high");
2968           DECL_GIMPLE_REG_P (perm_dest) = 1;
2969           add_referenced_var (perm_dest);
2970           if (BYTES_BIG_ENDIAN)
2971             {
2972               high_code = VEC_INTERLEAVE_HIGH_EXPR;
2973               low_code = VEC_INTERLEAVE_LOW_EXPR;
2974             }
2975           else
2976             {
2977               low_code = VEC_INTERLEAVE_HIGH_EXPR;
2978               high_code = VEC_INTERLEAVE_LOW_EXPR;
2979             }
2980           perm_stmt = gimple_build_assign_with_ops (high_code, perm_dest,
2981                                                     vect1, vect2);
2982           high = make_ssa_name (perm_dest, perm_stmt);
2983           gimple_assign_set_lhs (perm_stmt, high);
2984           vect_finish_stmt_generation (stmt, perm_stmt, gsi);
2985           VEC_replace (tree, *result_chain, 2*j, high);
2986
2987           /* Create interleaving stmt:
2988              in the case of big endian:
2989                                low  = interleave_low (vect1, vect2)
2990              and in the case of little endian:
2991                                low  = interleave_high (vect1, vect2).  */
2992           perm_dest = create_tmp_var (vectype, "vect_inter_low");
2993           DECL_GIMPLE_REG_P (perm_dest) = 1;
2994           add_referenced_var (perm_dest);
2995           perm_stmt = gimple_build_assign_with_ops (low_code, perm_dest,
2996                                                     vect1, vect2);
2997           low = make_ssa_name (perm_dest, perm_stmt);
2998           gimple_assign_set_lhs (perm_stmt, low);
2999           vect_finish_stmt_generation (stmt, perm_stmt, gsi);
3000           VEC_replace (tree, *result_chain, 2*j+1, low);
3001         }
3002       dr_chain = VEC_copy (tree, heap, *result_chain);
3003     }
3004   return true;
3005 }
3006
3007 /* Function vect_setup_realignment
3008
3009    This function is called when vectorizing an unaligned load using
3010    the dr_explicit_realign[_optimized] scheme.
3011    This function generates the following code at the loop prolog:
3012
3013       p = initial_addr;
3014    x  msq_init = *(floor(p));   # prolog load
3015       realignment_token = call target_builtin;
3016     loop:
3017    x  msq = phi (msq_init, ---)
3018
3019    The stmts marked with x are generated only for the case of
3020    dr_explicit_realign_optimized.
3021
3022    The code above sets up a new (vector) pointer, pointing to the first
3023    location accessed by STMT, and a "floor-aligned" load using that pointer.
3024    It also generates code to compute the "realignment-token" (if the relevant
3025    target hook was defined), and creates a phi-node at the loop-header bb
3026    whose arguments are the result of the prolog-load (created by this
3027    function) and the result of a load that takes place in the loop (to be
3028    created by the caller to this function).
3029
3030    For the case of dr_explicit_realign_optimized:
3031    The caller to this function uses the phi-result (msq) to create the
3032    realignment code inside the loop, and sets up the missing phi argument,
3033    as follows:
3034     loop:
3035       msq = phi (msq_init, lsq)
3036       lsq = *(floor(p'));        # load in loop
3037       result = realign_load (msq, lsq, realignment_token);
3038
3039    For the case of dr_explicit_realign:
3040     loop:
3041       msq = *(floor(p));        # load in loop
3042       p' = p + (VS-1);
3043       lsq = *(floor(p'));       # load in loop
3044       result = realign_load (msq, lsq, realignment_token);
3045
3046    Input:
3047    STMT - (scalar) load stmt to be vectorized. This load accesses
3048           a memory location that may be unaligned.
3049    BSI - place where new code is to be inserted.
3050    ALIGNMENT_SUPPORT_SCHEME - which of the two misalignment handling schemes
3051                               is used.
3052
3053    Output:
3054    REALIGNMENT_TOKEN - the result of a call to the builtin_mask_for_load
3055                        target hook, if defined.
3056    Return value - the result of the loop-header phi node.  */
3057
3058 tree
3059 vect_setup_realignment (gimple stmt, gimple_stmt_iterator *gsi,
3060                         tree *realignment_token,
3061                         enum dr_alignment_support alignment_support_scheme,
3062                         tree init_addr,
3063                         struct loop **at_loop)
3064 {
3065   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3066   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3067   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3068   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
3069   edge pe;
3070   tree scalar_dest = gimple_assign_lhs (stmt);
3071   tree vec_dest;
3072   gimple inc;
3073   tree ptr;
3074   tree data_ref;
3075   gimple new_stmt;
3076   basic_block new_bb;
3077   tree msq_init = NULL_TREE;
3078   tree new_temp;
3079   gimple phi_stmt;
3080   tree msq = NULL_TREE;
3081   gimple_seq stmts = NULL;
3082   bool inv_p;
3083   bool compute_in_loop = false;
3084   bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
3085   struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
3086   struct loop *loop_for_initial_load;
3087
3088   gcc_assert (alignment_support_scheme == dr_explicit_realign
3089               || alignment_support_scheme == dr_explicit_realign_optimized);
3090
3091   /* We need to generate three things:
3092      1. the misalignment computation
3093      2. the extra vector load (for the optimized realignment scheme).
3094      3. the phi node for the two vectors from which the realignment is
3095       done (for the optimized realignment scheme).
3096    */
3097
3098   /* 1. Determine where to generate the misalignment computation.
3099
3100      If INIT_ADDR is NULL_TREE, this indicates that the misalignment
3101      calculation will be generated by this function, outside the loop (in the
3102      preheader).  Otherwise, INIT_ADDR had already been computed for us by the
3103      caller, inside the loop.
3104
3105      Background: If the misalignment remains fixed throughout the iterations of
3106      the loop, then both realignment schemes are applicable, and also the
3107      misalignment computation can be done outside LOOP.  This is because we are
3108      vectorizing LOOP, and so the memory accesses in LOOP advance in steps that
3109      are a multiple of VS (the Vector Size), and therefore the misalignment in
3110      different vectorized LOOP iterations is always the same.
3111      The problem arises only if the memory access is in an inner-loop nested
3112      inside LOOP, which is now being vectorized using outer-loop vectorization.
3113      This is the only case when the misalignment of the memory access may not
3114      remain fixed throughout the iterations of the inner-loop (as explained in
3115      detail in vect_supportable_dr_alignment).  In this case, not only is the
3116      optimized realignment scheme not applicable, but also the misalignment
3117      computation (and generation of the realignment token that is passed to
3118      REALIGN_LOAD) have to be done inside the loop.
3119
3120      In short, INIT_ADDR indicates whether we are in a COMPUTE_IN_LOOP mode
3121      or not, which in turn determines if the misalignment is computed inside
3122      the inner-loop, or outside LOOP.  */
3123
3124   if (init_addr != NULL_TREE)
3125     {
3126       compute_in_loop = true;
3127       gcc_assert (alignment_support_scheme == dr_explicit_realign);
3128     }
3129
3130
3131   /* 2. Determine where to generate the extra vector load.
3132
3133      For the optimized realignment scheme, instead of generating two vector
3134      loads in each iteration, we generate a single extra vector load in the
3135      preheader of the loop, and in each iteration reuse the result of the
3136      vector load from the previous iteration.  In case the memory access is in
3137      an inner-loop nested inside LOOP, which is now being vectorized using
3138      outer-loop vectorization, we need to determine whether this initial vector
3139      load should be generated at the preheader of the inner-loop, or can be
3140      generated at the preheader of LOOP.  If the memory access has no evolution
3141      in LOOP, it can be generated in the preheader of LOOP. Otherwise, it has
3142      to be generated inside LOOP (in the preheader of the inner-loop).  */
3143
3144   if (nested_in_vect_loop)
3145     {
3146       tree outerloop_step = STMT_VINFO_DR_STEP (stmt_info);
3147       bool invariant_in_outerloop =
3148             (tree_int_cst_compare (outerloop_step, size_zero_node) == 0);
3149       loop_for_initial_load = (invariant_in_outerloop ? loop : loop->inner);
3150     }
3151   else
3152     loop_for_initial_load = loop;
3153   if (at_loop)
3154     *at_loop = loop_for_initial_load;
3155
3156   /* 3. For the case of the optimized realignment, create the first vector
3157       load at the loop preheader.  */
3158
3159   if (alignment_support_scheme == dr_explicit_realign_optimized)
3160     {
3161       /* Create msq_init = *(floor(p1)) in the loop preheader  */
3162
3163       gcc_assert (!compute_in_loop);
3164       pe = loop_preheader_edge (loop_for_initial_load);
3165       vec_dest = vect_create_destination_var (scalar_dest, vectype);
3166       ptr = vect_create_data_ref_ptr (stmt, loop_for_initial_load, NULL_TREE,
3167                                       &init_addr, &inc, true, &inv_p);
3168       data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
3169       new_stmt = gimple_build_assign (vec_dest, data_ref);
3170       new_temp = make_ssa_name (vec_dest, new_stmt);
3171       gimple_assign_set_lhs (new_stmt, new_temp);
3172       mark_symbols_for_renaming (new_stmt);
3173       new_bb = gsi_insert_on_edge_immediate (pe, new_stmt);
3174       gcc_assert (!new_bb);
3175       msq_init = gimple_assign_lhs (new_stmt);
3176     }
3177
3178   /* 4. Create realignment token using a target builtin, if available.
3179       It is done either inside the containing loop, or before LOOP (as
3180       determined above).  */
3181
3182   if (targetm.vectorize.builtin_mask_for_load)
3183     {
3184       tree builtin_decl;
3185
3186       /* Compute INIT_ADDR - the initial addressed accessed by this memref.  */
3187       if (compute_in_loop)
3188         gcc_assert (init_addr); /* already computed by the caller.  */
3189       else
3190         {
3191           /* Generate the INIT_ADDR computation outside LOOP.  */
3192           init_addr = vect_create_addr_base_for_vector_ref (stmt, &stmts,
3193                                                         NULL_TREE, loop);
3194           pe = loop_preheader_edge (loop);
3195           new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
3196           gcc_assert (!new_bb);
3197         }
3198
3199       builtin_decl = targetm.vectorize.builtin_mask_for_load ();
3200       new_stmt = gimple_build_call (builtin_decl, 1, init_addr);
3201       vec_dest =
3202         vect_create_destination_var (scalar_dest,
3203                                      gimple_call_return_type (new_stmt));
3204       new_temp = make_ssa_name (vec_dest, new_stmt);
3205       gimple_call_set_lhs (new_stmt, new_temp);
3206
3207       if (compute_in_loop)
3208         gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
3209       else
3210         {
3211           /* Generate the misalignment computation outside LOOP.  */
3212           pe = loop_preheader_edge (loop);
3213           new_bb = gsi_insert_on_edge_immediate (pe, new_stmt);
3214           gcc_assert (!new_bb);
3215         }
3216
3217       *realignment_token = gimple_call_lhs (new_stmt);
3218
3219       /* The result of the CALL_EXPR to this builtin is determined from
3220          the value of the parameter and no global variables are touched
3221          which makes the builtin a "const" function.  Requiring the
3222          builtin to have the "const" attribute makes it unnecessary
3223          to call mark_call_clobbered.  */
3224       gcc_assert (TREE_READONLY (builtin_decl));
3225     }
3226
3227   if (alignment_support_scheme == dr_explicit_realign)
3228     return msq;
3229
3230   gcc_assert (!compute_in_loop);
3231   gcc_assert (alignment_support_scheme == dr_explicit_realign_optimized);
3232
3233
3234   /* 5. Create msq = phi <msq_init, lsq> in loop  */
3235
3236   pe = loop_preheader_edge (containing_loop);
3237   vec_dest = vect_create_destination_var (scalar_dest, vectype);
3238   msq = make_ssa_name (vec_dest, NULL);
3239   phi_stmt = create_phi_node (msq, containing_loop->header);
3240   SSA_NAME_DEF_STMT (msq) = phi_stmt;
3241   add_phi_arg (phi_stmt, msq_init, pe, UNKNOWN_LOCATION);
3242
3243   return msq;
3244 }
3245
3246
3247 /* Function vect_strided_load_supported.
3248
3249    Returns TRUE is EXTRACT_EVEN and EXTRACT_ODD operations are supported,
3250    and FALSE otherwise.  */
3251
3252 bool
3253 vect_strided_load_supported (tree vectype)
3254 {
3255   optab perm_even_optab, perm_odd_optab;
3256   int mode;
3257
3258   mode = (int) TYPE_MODE (vectype);
3259
3260   perm_even_optab = optab_for_tree_code (VEC_EXTRACT_EVEN_EXPR, vectype,
3261                                          optab_default);
3262   if (!perm_even_optab)
3263     {
3264       if (vect_print_dump_info (REPORT_DETAILS))
3265         fprintf (vect_dump, "no optab for perm_even.");
3266       return false;
3267     }
3268
3269   if (optab_handler (perm_even_optab, mode)->insn_code == CODE_FOR_nothing)
3270     {
3271       if (vect_print_dump_info (REPORT_DETAILS))
3272         fprintf (vect_dump, "perm_even op not supported by target.");
3273       return false;
3274     }
3275
3276   perm_odd_optab = optab_for_tree_code (VEC_EXTRACT_ODD_EXPR, vectype,
3277                                         optab_default);
3278   if (!perm_odd_optab)
3279     {
3280       if (vect_print_dump_info (REPORT_DETAILS))
3281         fprintf (vect_dump, "no optab for perm_odd.");
3282       return false;
3283     }
3284
3285   if (optab_handler (perm_odd_optab, mode)->insn_code == CODE_FOR_nothing)
3286     {
3287       if (vect_print_dump_info (REPORT_DETAILS))
3288         fprintf (vect_dump, "perm_odd op not supported by target.");
3289       return false;
3290     }
3291   return true;
3292 }
3293
3294
3295 /* Function vect_permute_load_chain.
3296
3297    Given a chain of interleaved loads in DR_CHAIN of LENGTH that must be
3298    a power of 2, generate extract_even/odd stmts to reorder the input data
3299    correctly. Return the final references for loads in RESULT_CHAIN.
3300
3301    E.g., LENGTH is 4 and the scalar type is short, i.e., VF is 8.
3302    The input is 4 vectors each containing 8 elements. We assign a number to each
3303    element, the input sequence is:
3304
3305    1st vec:   0  1  2  3  4  5  6  7
3306    2nd vec:   8  9 10 11 12 13 14 15
3307    3rd vec:  16 17 18 19 20 21 22 23
3308    4th vec:  24 25 26 27 28 29 30 31
3309
3310    The output sequence should be:
3311
3312    1st vec:  0 4  8 12 16 20 24 28
3313    2nd vec:  1 5  9 13 17 21 25 29
3314    3rd vec:  2 6 10 14 18 22 26 30
3315    4th vec:  3 7 11 15 19 23 27 31
3316
3317    i.e., the first output vector should contain the first elements of each
3318    interleaving group, etc.
3319
3320    We use extract_even/odd instructions to create such output. The input of each
3321    extract_even/odd operation is two vectors
3322    1st vec    2nd vec
3323    0 1 2 3    4 5 6 7
3324
3325    and the output is the vector of extracted even/odd elements. The output of
3326    extract_even will be:   0 2 4 6
3327    and of extract_odd:     1 3 5 7
3328
3329
3330    The permutation is done in log LENGTH stages. In each stage extract_even and
3331    extract_odd stmts are created for each pair of vectors in DR_CHAIN in their
3332    order. In our example,
3333
3334    E1: extract_even (1st vec, 2nd vec)
3335    E2: extract_odd (1st vec, 2nd vec)
3336    E3: extract_even (3rd vec, 4th vec)
3337    E4: extract_odd (3rd vec, 4th vec)
3338
3339    The output for the first stage will be:
3340
3341    E1:  0  2  4  6  8 10 12 14
3342    E2:  1  3  5  7  9 11 13 15
3343    E3: 16 18 20 22 24 26 28 30
3344    E4: 17 19 21 23 25 27 29 31
3345
3346    In order to proceed and create the correct sequence for the next stage (or
3347    for the correct output, if the second stage is the last one, as in our
3348    example), we first put the output of extract_even operation and then the
3349    output of extract_odd in RESULT_CHAIN (which is then copied to DR_CHAIN).
3350    The input for the second stage is:
3351
3352    1st vec (E1):  0  2  4  6  8 10 12 14
3353    2nd vec (E3): 16 18 20 22 24 26 28 30
3354    3rd vec (E2):  1  3  5  7  9 11 13 15
3355    4th vec (E4): 17 19 21 23 25 27 29 31
3356
3357    The output of the second stage:
3358
3359    E1: 0 4  8 12 16 20 24 28
3360    E2: 2 6 10 14 18 22 26 30
3361    E3: 1 5  9 13 17 21 25 29
3362    E4: 3 7 11 15 19 23 27 31
3363
3364    And RESULT_CHAIN after reordering:
3365
3366    1st vec (E1):  0 4  8 12 16 20 24 28
3367    2nd vec (E3):  1 5  9 13 17 21 25 29
3368    3rd vec (E2):  2 6 10 14 18 22 26 30
3369    4th vec (E4):  3 7 11 15 19 23 27 31.  */
3370
3371 bool
3372 vect_permute_load_chain (VEC(tree,heap) *dr_chain,
3373                          unsigned int length,
3374                          gimple stmt,
3375                          gimple_stmt_iterator *gsi,
3376                          VEC(tree,heap) **result_chain)
3377 {
3378   tree perm_dest, data_ref, first_vect, second_vect;
3379   gimple perm_stmt;
3380   tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
3381   int i;
3382   unsigned int j;
3383
3384   /* Check that the operation is supported.  */
3385   if (!vect_strided_load_supported (vectype))
3386     return false;
3387
3388   *result_chain = VEC_copy (tree, heap, dr_chain);
3389   for (i = 0; i < exact_log2 (length); i++)
3390     {
3391       for (j = 0; j < length; j +=2)
3392         {
3393           first_vect = VEC_index (tree, dr_chain, j);
3394           second_vect = VEC_index (tree, dr_chain, j+1);
3395
3396           /* data_ref = permute_even (first_data_ref, second_data_ref);  */
3397           perm_dest = create_tmp_var (vectype, "vect_perm_even");
3398           DECL_GIMPLE_REG_P (perm_dest) = 1;
3399           add_referenced_var (perm_dest);
3400
3401           perm_stmt = gimple_build_assign_with_ops (VEC_EXTRACT_EVEN_EXPR,
3402                                                     perm_dest, first_vect,
3403                                                     second_vect);
3404
3405           data_ref = make_ssa_name (perm_dest, perm_stmt);
3406           gimple_assign_set_lhs (perm_stmt, data_ref);
3407           vect_finish_stmt_generation (stmt, perm_stmt, gsi);
3408           mark_symbols_for_renaming (perm_stmt);
3409
3410           VEC_replace (tree, *result_chain, j/2, data_ref);
3411
3412           /* data_ref = permute_odd (first_data_ref, second_data_ref);  */
3413           perm_dest = create_tmp_var (vectype, "vect_perm_odd");
3414           DECL_GIMPLE_REG_P (perm_dest) = 1;
3415           add_referenced_var (perm_dest);
3416
3417           perm_stmt = gimple_build_assign_with_ops (VEC_EXTRACT_ODD_EXPR,
3418                                                     perm_dest, first_vect,
3419                                                     second_vect);
3420           data_ref = make_ssa_name (perm_dest, perm_stmt);
3421           gimple_assign_set_lhs (perm_stmt, data_ref);
3422           vect_finish_stmt_generation (stmt, perm_stmt, gsi);
3423           mark_symbols_for_renaming (perm_stmt);
3424
3425           VEC_replace (tree, *result_chain, j/2+length/2, data_ref);
3426         }
3427       dr_chain = VEC_copy (tree, heap, *result_chain);
3428     }
3429   return true;
3430 }
3431
3432
3433 /* Function vect_transform_strided_load.
3434
3435    Given a chain of input interleaved data-refs (in DR_CHAIN), build statements
3436    to perform their permutation and ascribe the result vectorized statements to
3437    the scalar statements.
3438 */
3439
3440 bool
3441 vect_transform_strided_load (gimple stmt, VEC(tree,heap) *dr_chain, int size,
3442                              gimple_stmt_iterator *gsi)
3443 {
3444   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3445   gimple first_stmt = DR_GROUP_FIRST_DR (stmt_info);
3446   gimple next_stmt, new_stmt;
3447   VEC(tree,heap) *result_chain = NULL;
3448   unsigned int i, gap_count;
3449   tree tmp_data_ref;
3450
3451   /* DR_CHAIN contains input data-refs that are a part of the interleaving.
3452      RESULT_CHAIN is the output of vect_permute_load_chain, it contains permuted
3453      vectors, that are ready for vector computation.  */
3454   result_chain = VEC_alloc (tree, heap, size);
3455   /* Permute.  */
3456   if (!vect_permute_load_chain (dr_chain, size, stmt, gsi, &result_chain))
3457     return false;
3458
3459   /* Put a permuted data-ref in the VECTORIZED_STMT field.
3460      Since we scan the chain starting from it's first node, their order
3461      corresponds the order of data-refs in RESULT_CHAIN.  */
3462   next_stmt = first_stmt;
3463   gap_count = 1;
3464   for (i = 0; VEC_iterate (tree, result_chain, i, tmp_data_ref); i++)
3465     {
3466       if (!next_stmt)
3467         break;
3468
3469       /* Skip the gaps. Loads created for the gaps will be removed by dead
3470        code elimination pass later. No need to check for the first stmt in
3471        the group, since it always exists.
3472        DR_GROUP_GAP is the number of steps in elements from the previous
3473        access (if there is no gap DR_GROUP_GAP is 1). We skip loads that
3474        correspond to the gaps.
3475       */
3476       if (next_stmt != first_stmt
3477           && gap_count < DR_GROUP_GAP (vinfo_for_stmt (next_stmt)))
3478       {
3479         gap_count++;
3480         continue;
3481       }
3482
3483       while (next_stmt)
3484         {
3485           new_stmt = SSA_NAME_DEF_STMT (tmp_data_ref);
3486           /* We assume that if VEC_STMT is not NULL, this is a case of multiple
3487              copies, and we put the new vector statement in the first available
3488              RELATED_STMT.  */
3489           if (!STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)))
3490             STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)) = new_stmt;
3491           else
3492             {
3493               if (!DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next_stmt)))
3494                 {
3495                   gimple prev_stmt =
3496                     STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt));
3497                   gimple rel_stmt =
3498                     STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt));
3499                   while (rel_stmt)
3500                     {
3501                       prev_stmt = rel_stmt;
3502                       rel_stmt =
3503                         STMT_VINFO_RELATED_STMT (vinfo_for_stmt (rel_stmt));
3504                     }
3505
3506                   STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)) =
3507                     new_stmt;
3508                 }
3509             }
3510
3511           next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
3512           gap_count = 1;
3513           /* If NEXT_STMT accesses the same DR as the previous statement,
3514              put the same TMP_DATA_REF as its vectorized statement; otherwise
3515              get the next data-ref from RESULT_CHAIN.  */
3516           if (!next_stmt || !DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next_stmt)))
3517             break;
3518         }
3519     }
3520
3521   VEC_free (tree, heap, result_chain);
3522   return true;
3523 }
3524
3525 /* Function vect_force_dr_alignment_p.
3526
3527    Returns whether the alignment of a DECL can be forced to be aligned
3528    on ALIGNMENT bit boundary.  */
3529
3530 bool
3531 vect_can_force_dr_alignment_p (const_tree decl, unsigned int alignment)
3532 {
3533   if (TREE_CODE (decl) != VAR_DECL)
3534     return false;
3535
3536   if (DECL_EXTERNAL (decl))
3537     return false;
3538
3539   if (TREE_ASM_WRITTEN (decl))
3540     return false;
3541
3542   if (TREE_STATIC (decl))
3543     return (alignment <= MAX_OFILE_ALIGNMENT);
3544   else
3545     return (alignment <= MAX_STACK_ALIGNMENT);
3546 }
3547
3548 /* Function vect_supportable_dr_alignment
3549
3550    Return whether the data reference DR is supported with respect to its
3551    alignment.  */
3552
3553 enum dr_alignment_support
3554 vect_supportable_dr_alignment (struct data_reference *dr)
3555 {
3556   gimple stmt = DR_STMT (dr);
3557   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3558   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3559   enum machine_mode mode = TYPE_MODE (vectype);
3560   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3561   struct loop *vect_loop = NULL;
3562   bool nested_in_vect_loop = false;
3563
3564   if (aligned_access_p (dr))
3565     return dr_aligned;
3566
3567   if (!loop_vinfo)
3568     /* FORNOW: Misaligned accesses are supported only in loops.  */
3569     return dr_unaligned_unsupported;
3570
3571   vect_loop = LOOP_VINFO_LOOP (loop_vinfo);
3572   nested_in_vect_loop = nested_in_vect_loop_p (vect_loop, stmt);
3573
3574   /* Possibly unaligned access.  */
3575
3576   /* We can choose between using the implicit realignment scheme (generating
3577      a misaligned_move stmt) and the explicit realignment scheme (generating
3578      aligned loads with a REALIGN_LOAD). There are two variants to the explicit
3579      realignment scheme: optimized, and unoptimized.
3580      We can optimize the realignment only if the step between consecutive
3581      vector loads is equal to the vector size.  Since the vector memory
3582      accesses advance in steps of VS (Vector Size) in the vectorized loop, it
3583      is guaranteed that the misalignment amount remains the same throughout the
3584      execution of the vectorized loop.  Therefore, we can create the
3585      "realignment token" (the permutation mask that is passed to REALIGN_LOAD)
3586      at the loop preheader.
3587
3588      However, in the case of outer-loop vectorization, when vectorizing a
3589      memory access in the inner-loop nested within the LOOP that is now being
3590      vectorized, while it is guaranteed that the misalignment of the
3591      vectorized memory access will remain the same in different outer-loop
3592      iterations, it is *not* guaranteed that is will remain the same throughout
3593      the execution of the inner-loop.  This is because the inner-loop advances
3594      with the original scalar step (and not in steps of VS).  If the inner-loop
3595      step happens to be a multiple of VS, then the misalignment remains fixed
3596      and we can use the optimized realignment scheme.  For example:
3597
3598       for (i=0; i<N; i++)
3599         for (j=0; j<M; j++)
3600           s += a[i+j];
3601
3602      When vectorizing the i-loop in the above example, the step between
3603      consecutive vector loads is 1, and so the misalignment does not remain
3604      fixed across the execution of the inner-loop, and the realignment cannot
3605      be optimized (as illustrated in the following pseudo vectorized loop):
3606
3607       for (i=0; i<N; i+=4)
3608         for (j=0; j<M; j++){
3609           vs += vp[i+j]; // misalignment of &vp[i+j] is {0,1,2,3,0,1,2,3,...}
3610                          // when j is {0,1,2,3,4,5,6,7,...} respectively.
3611                          // (assuming that we start from an aligned address).
3612           }
3613
3614      We therefore have to use the unoptimized realignment scheme:
3615
3616       for (i=0; i<N; i+=4)
3617           for (j=k; j<M; j+=4)
3618           vs += vp[i+j]; // misalignment of &vp[i+j] is always k (assuming
3619                            // that the misalignment of the initial address is
3620                            // 0).
3621
3622      The loop can then be vectorized as follows:
3623
3624       for (k=0; k<4; k++){
3625         rt = get_realignment_token (&vp[k]);
3626         for (i=0; i<N; i+=4){
3627           v1 = vp[i+k];
3628           for (j=k; j<M; j+=4){
3629             v2 = vp[i+j+VS-1];
3630             va = REALIGN_LOAD <v1,v2,rt>;
3631             vs += va;
3632             v1 = v2;
3633           }
3634         }
3635     } */
3636
3637   if (DR_IS_READ (dr))
3638     {
3639       bool is_packed = false;
3640       tree type = (TREE_TYPE (DR_REF (dr)));
3641
3642       if (optab_handler (vec_realign_load_optab, mode)->insn_code !=
3643                                                              CODE_FOR_nothing
3644           && (!targetm.vectorize.builtin_mask_for_load
3645               || targetm.vectorize.builtin_mask_for_load ()))
3646         {
3647           tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3648           if (nested_in_vect_loop
3649               && (TREE_INT_CST_LOW (DR_STEP (dr))
3650                   != GET_MODE_SIZE (TYPE_MODE (vectype))))
3651             return dr_explicit_realign;
3652           else
3653             return dr_explicit_realign_optimized;
3654         }
3655       if (!known_alignment_for_access_p (dr))
3656         {
3657           tree ba = DR_BASE_OBJECT (dr);
3658
3659           if (ba)
3660             is_packed = contains_packed_reference (ba);
3661         }
3662
3663       if (targetm.vectorize.
3664           builtin_support_vector_misalignment (mode, type,
3665                                                DR_MISALIGNMENT (dr), is_packed))
3666         /* Can't software pipeline the loads, but can at least do them.  */
3667         return dr_unaligned_supported;
3668     }
3669   else
3670     {
3671       bool is_packed = false;
3672       tree type = (TREE_TYPE (DR_REF (dr)));
3673
3674       if (!known_alignment_for_access_p (dr))
3675         {
3676           tree ba = DR_BASE_OBJECT (dr);
3677
3678           if (ba)
3679             is_packed = contains_packed_reference (ba);
3680         }
3681
3682      if (targetm.vectorize.
3683          builtin_support_vector_misalignment (mode, type,
3684                                               DR_MISALIGNMENT (dr), is_packed))
3685        return dr_unaligned_supported;
3686     }
3687
3688   /* Unsupported.  */
3689   return dr_unaligned_unsupported;
3690 }