OSDN Git Service

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