xref: /dflybsd-src/contrib/gcc-8.0/gcc/tree-vectorizer.h (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Vectorizer
238fd1498Szrj    Copyright (C) 2003-2018 Free Software Foundation, Inc.
338fd1498Szrj    Contributed by Dorit Naishlos <dorit@il.ibm.com>
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj #ifndef GCC_TREE_VECTORIZER_H
2238fd1498Szrj #define GCC_TREE_VECTORIZER_H
2338fd1498Szrj 
2438fd1498Szrj #include "tree-data-ref.h"
2538fd1498Szrj #include "tree-hash-traits.h"
2638fd1498Szrj #include "target.h"
2738fd1498Szrj 
2838fd1498Szrj /* Used for naming of new temporaries.  */
2938fd1498Szrj enum vect_var_kind {
3038fd1498Szrj   vect_simple_var,
3138fd1498Szrj   vect_pointer_var,
3238fd1498Szrj   vect_scalar_var,
3338fd1498Szrj   vect_mask_var
3438fd1498Szrj };
3538fd1498Szrj 
3638fd1498Szrj /* Defines type of operation.  */
3738fd1498Szrj enum operation_type {
3838fd1498Szrj   unary_op = 1,
3938fd1498Szrj   binary_op,
4038fd1498Szrj   ternary_op
4138fd1498Szrj };
4238fd1498Szrj 
4338fd1498Szrj /* Define type of available alignment support.  */
4438fd1498Szrj enum dr_alignment_support {
4538fd1498Szrj   dr_unaligned_unsupported,
4638fd1498Szrj   dr_unaligned_supported,
4738fd1498Szrj   dr_explicit_realign,
4838fd1498Szrj   dr_explicit_realign_optimized,
4938fd1498Szrj   dr_aligned
5038fd1498Szrj };
5138fd1498Szrj 
5238fd1498Szrj /* Define type of def-use cross-iteration cycle.  */
5338fd1498Szrj enum vect_def_type {
5438fd1498Szrj   vect_uninitialized_def = 0,
5538fd1498Szrj   vect_constant_def = 1,
5638fd1498Szrj   vect_external_def,
5738fd1498Szrj   vect_internal_def,
5838fd1498Szrj   vect_induction_def,
5938fd1498Szrj   vect_reduction_def,
6038fd1498Szrj   vect_double_reduction_def,
6138fd1498Szrj   vect_nested_cycle,
6238fd1498Szrj   vect_unknown_def_type
6338fd1498Szrj };
6438fd1498Szrj 
6538fd1498Szrj /* Define type of reduction.  */
6638fd1498Szrj enum vect_reduction_type {
6738fd1498Szrj   TREE_CODE_REDUCTION,
6838fd1498Szrj   COND_REDUCTION,
6938fd1498Szrj   INTEGER_INDUC_COND_REDUCTION,
7038fd1498Szrj   CONST_COND_REDUCTION,
7138fd1498Szrj 
7238fd1498Szrj   /* Retain a scalar phi and use a FOLD_EXTRACT_LAST within the loop
7338fd1498Szrj      to implement:
7438fd1498Szrj 
7538fd1498Szrj        for (int i = 0; i < VF; ++i)
7638fd1498Szrj          res = cond[i] ? val[i] : res;  */
7738fd1498Szrj   EXTRACT_LAST_REDUCTION,
7838fd1498Szrj 
7938fd1498Szrj   /* Use a folding reduction within the loop to implement:
8038fd1498Szrj 
8138fd1498Szrj        for (int i = 0; i < VF; ++i)
8238fd1498Szrj 	 res = res OP val[i];
8338fd1498Szrj 
8438fd1498Szrj      (with no reassocation).  */
8538fd1498Szrj   FOLD_LEFT_REDUCTION
8638fd1498Szrj };
8738fd1498Szrj 
8838fd1498Szrj #define VECTORIZABLE_CYCLE_DEF(D) (((D) == vect_reduction_def)           \
8938fd1498Szrj                                    || ((D) == vect_double_reduction_def) \
9038fd1498Szrj                                    || ((D) == vect_nested_cycle))
9138fd1498Szrj 
9238fd1498Szrj /* Structure to encapsulate information about a group of like
9338fd1498Szrj    instructions to be presented to the target cost model.  */
9438fd1498Szrj struct stmt_info_for_cost {
9538fd1498Szrj   int count;
9638fd1498Szrj   enum vect_cost_for_stmt kind;
9738fd1498Szrj   gimple *stmt;
9838fd1498Szrj   int misalign;
9938fd1498Szrj };
10038fd1498Szrj 
10138fd1498Szrj typedef vec<stmt_info_for_cost> stmt_vector_for_cost;
10238fd1498Szrj 
10338fd1498Szrj /* Maps base addresses to an innermost_loop_behavior that gives the maximum
10438fd1498Szrj    known alignment for that base.  */
10538fd1498Szrj typedef hash_map<tree_operand_hash,
10638fd1498Szrj 		 innermost_loop_behavior *> vec_base_alignments;
10738fd1498Szrj 
10838fd1498Szrj /************************************************************************
10938fd1498Szrj   SLP
11038fd1498Szrj  ************************************************************************/
11138fd1498Szrj typedef struct _slp_tree *slp_tree;
11238fd1498Szrj 
11338fd1498Szrj /* A computation tree of an SLP instance.  Each node corresponds to a group of
11438fd1498Szrj    stmts to be packed in a SIMD stmt.  */
11538fd1498Szrj struct _slp_tree {
11638fd1498Szrj   /* Nodes that contain def-stmts of this node statements operands.  */
11738fd1498Szrj   vec<slp_tree> children;
11838fd1498Szrj   /* A group of scalar stmts to be vectorized together.  */
11938fd1498Szrj   vec<gimple *> stmts;
12038fd1498Szrj   /* Load permutation relative to the stores, NULL if there is no
12138fd1498Szrj      permutation.  */
12238fd1498Szrj   vec<unsigned> load_permutation;
12338fd1498Szrj   /* Vectorized stmt/s.  */
12438fd1498Szrj   vec<gimple *> vec_stmts;
12538fd1498Szrj   /* Number of vector stmts that are created to replace the group of scalar
12638fd1498Szrj      stmts. It is calculated during the transformation phase as the number of
12738fd1498Szrj      scalar elements in one scalar iteration (GROUP_SIZE) multiplied by VF
12838fd1498Szrj      divided by vector size.  */
12938fd1498Szrj   unsigned int vec_stmts_size;
13038fd1498Szrj   /* Whether the scalar computations use two different operators.  */
13138fd1498Szrj   bool two_operators;
13238fd1498Szrj   /* The DEF type of this node.  */
13338fd1498Szrj   enum vect_def_type def_type;
13438fd1498Szrj };
13538fd1498Szrj 
13638fd1498Szrj 
13738fd1498Szrj /* SLP instance is a sequence of stmts in a loop that can be packed into
13838fd1498Szrj    SIMD stmts.  */
13938fd1498Szrj typedef struct _slp_instance {
14038fd1498Szrj   /* The root of SLP tree.  */
14138fd1498Szrj   slp_tree root;
14238fd1498Szrj 
14338fd1498Szrj   /* Size of groups of scalar stmts that will be replaced by SIMD stmt/s.  */
14438fd1498Szrj   unsigned int group_size;
14538fd1498Szrj 
14638fd1498Szrj   /* The unrolling factor required to vectorized this SLP instance.  */
14738fd1498Szrj   poly_uint64 unrolling_factor;
14838fd1498Szrj 
14938fd1498Szrj   /* The group of nodes that contain loads of this SLP instance.  */
15038fd1498Szrj   vec<slp_tree> loads;
15138fd1498Szrj 
15238fd1498Szrj   /* The SLP node containing the reduction PHIs.  */
15338fd1498Szrj   slp_tree reduc_phis;
15438fd1498Szrj } *slp_instance;
15538fd1498Szrj 
15638fd1498Szrj 
15738fd1498Szrj /* Access Functions.  */
15838fd1498Szrj #define SLP_INSTANCE_TREE(S)                     (S)->root
15938fd1498Szrj #define SLP_INSTANCE_GROUP_SIZE(S)               (S)->group_size
16038fd1498Szrj #define SLP_INSTANCE_UNROLLING_FACTOR(S)         (S)->unrolling_factor
16138fd1498Szrj #define SLP_INSTANCE_LOADS(S)                    (S)->loads
16238fd1498Szrj 
16338fd1498Szrj #define SLP_TREE_CHILDREN(S)                     (S)->children
16438fd1498Szrj #define SLP_TREE_SCALAR_STMTS(S)                 (S)->stmts
16538fd1498Szrj #define SLP_TREE_VEC_STMTS(S)                    (S)->vec_stmts
16638fd1498Szrj #define SLP_TREE_NUMBER_OF_VEC_STMTS(S)          (S)->vec_stmts_size
16738fd1498Szrj #define SLP_TREE_LOAD_PERMUTATION(S)             (S)->load_permutation
16838fd1498Szrj #define SLP_TREE_TWO_OPERATORS(S)		 (S)->two_operators
16938fd1498Szrj #define SLP_TREE_DEF_TYPE(S)			 (S)->def_type
17038fd1498Szrj 
17138fd1498Szrj 
17238fd1498Szrj 
17338fd1498Szrj /* Describes two objects whose addresses must be unequal for the vectorized
17438fd1498Szrj    loop to be valid.  */
17538fd1498Szrj typedef std::pair<tree, tree> vec_object_pair;
17638fd1498Szrj 
17738fd1498Szrj /* Records that vectorization is only possible if abs (EXPR) >= MIN_VALUE.
17838fd1498Szrj    UNSIGNED_P is true if we can assume that abs (EXPR) == EXPR.  */
17938fd1498Szrj struct vec_lower_bound {
vec_lower_boundvec_lower_bound18038fd1498Szrj   vec_lower_bound () {}
vec_lower_boundvec_lower_bound18138fd1498Szrj   vec_lower_bound (tree e, bool u, poly_uint64 m)
18238fd1498Szrj     : expr (e), unsigned_p (u), min_value (m) {}
18338fd1498Szrj 
18438fd1498Szrj   tree expr;
18538fd1498Szrj   bool unsigned_p;
18638fd1498Szrj   poly_uint64 min_value;
18738fd1498Szrj };
18838fd1498Szrj 
18938fd1498Szrj /* Vectorizer state common between loop and basic-block vectorization.  */
19038fd1498Szrj struct vec_info {
19138fd1498Szrj   enum vec_kind { bb, loop };
19238fd1498Szrj 
19338fd1498Szrj   vec_info (vec_kind, void *);
19438fd1498Szrj   ~vec_info ();
19538fd1498Szrj 
19638fd1498Szrj   /* The type of vectorization.  */
19738fd1498Szrj   vec_kind kind;
19838fd1498Szrj 
19938fd1498Szrj   /* All SLP instances.  */
20038fd1498Szrj   auto_vec<slp_instance> slp_instances;
20138fd1498Szrj 
20238fd1498Szrj   /* All data references.  Freed by free_data_refs, so not an auto_vec.  */
20338fd1498Szrj   vec<data_reference_p> datarefs;
20438fd1498Szrj 
20538fd1498Szrj   /* Maps base addresses to an innermost_loop_behavior that gives the maximum
20638fd1498Szrj      known alignment for that base.  */
20738fd1498Szrj   vec_base_alignments base_alignments;
20838fd1498Szrj 
20938fd1498Szrj   /* All data dependences.  Freed by free_dependence_relations, so not
21038fd1498Szrj      an auto_vec.  */
21138fd1498Szrj   vec<ddr_p> ddrs;
21238fd1498Szrj 
21338fd1498Szrj   /* All interleaving chains of stores, represented by the first
21438fd1498Szrj      stmt in the chain.  */
21538fd1498Szrj   auto_vec<gimple *> grouped_stores;
21638fd1498Szrj 
21738fd1498Szrj   /* Cost data used by the target cost model.  */
21838fd1498Szrj   void *target_cost_data;
21938fd1498Szrj };
22038fd1498Szrj 
22138fd1498Szrj struct _loop_vec_info;
22238fd1498Szrj struct _bb_vec_info;
22338fd1498Szrj 
22438fd1498Szrj template<>
22538fd1498Szrj template<>
22638fd1498Szrj inline bool
test(vec_info * i)22738fd1498Szrj is_a_helper <_loop_vec_info *>::test (vec_info *i)
22838fd1498Szrj {
22938fd1498Szrj   return i->kind == vec_info::loop;
23038fd1498Szrj }
23138fd1498Szrj 
23238fd1498Szrj template<>
23338fd1498Szrj template<>
23438fd1498Szrj inline bool
test(vec_info * i)23538fd1498Szrj is_a_helper <_bb_vec_info *>::test (vec_info *i)
23638fd1498Szrj {
23738fd1498Szrj   return i->kind == vec_info::bb;
23838fd1498Szrj }
23938fd1498Szrj 
24038fd1498Szrj 
24138fd1498Szrj /* In general, we can divide the vector statements in a vectorized loop
24238fd1498Szrj    into related groups ("rgroups") and say that for each rgroup there is
24338fd1498Szrj    some nS such that the rgroup operates on nS values from one scalar
24438fd1498Szrj    iteration followed by nS values from the next.  That is, if VF is the
24538fd1498Szrj    vectorization factor of the loop, the rgroup operates on a sequence:
24638fd1498Szrj 
24738fd1498Szrj      (1,1) (1,2) ... (1,nS) (2,1) ... (2,nS) ... (VF,1) ... (VF,nS)
24838fd1498Szrj 
24938fd1498Szrj    where (i,j) represents a scalar value with index j in a scalar
25038fd1498Szrj    iteration with index i.
25138fd1498Szrj 
25238fd1498Szrj    [ We use the term "rgroup" to emphasise that this grouping isn't
25338fd1498Szrj      necessarily the same as the grouping of statements used elsewhere.
25438fd1498Szrj      For example, if we implement a group of scalar loads using gather
25538fd1498Szrj      loads, we'll use a separate gather load for each scalar load, and
25638fd1498Szrj      thus each gather load will belong to its own rgroup. ]
25738fd1498Szrj 
25838fd1498Szrj    In general this sequence will occupy nV vectors concatenated
25938fd1498Szrj    together.  If these vectors have nL lanes each, the total number
26038fd1498Szrj    of scalar values N is given by:
26138fd1498Szrj 
26238fd1498Szrj        N = nS * VF = nV * nL
26338fd1498Szrj 
26438fd1498Szrj    None of nS, VF, nV and nL are required to be a power of 2.  nS and nV
26538fd1498Szrj    are compile-time constants but VF and nL can be variable (if the target
26638fd1498Szrj    supports variable-length vectors).
26738fd1498Szrj 
26838fd1498Szrj    In classical vectorization, each iteration of the vector loop would
26938fd1498Szrj    handle exactly VF iterations of the original scalar loop.  However,
27038fd1498Szrj    in a fully-masked loop, a particular iteration of the vector loop
27138fd1498Szrj    might handle fewer than VF iterations of the scalar loop.  The vector
27238fd1498Szrj    lanes that correspond to iterations of the scalar loop are said to be
27338fd1498Szrj    "active" and the other lanes are said to be "inactive".
27438fd1498Szrj 
27538fd1498Szrj    In a fully-masked loop, many rgroups need to be masked to ensure that
27638fd1498Szrj    they have no effect for the inactive lanes.  Each such rgroup needs a
27738fd1498Szrj    sequence of booleans in the same order as above, but with each (i,j)
27838fd1498Szrj    replaced by a boolean that indicates whether iteration i is active.
27938fd1498Szrj    This sequence occupies nV vector masks that again have nL lanes each.
28038fd1498Szrj    Thus the mask sequence as a whole consists of VF independent booleans
28138fd1498Szrj    that are each repeated nS times.
28238fd1498Szrj 
28338fd1498Szrj    We make the simplifying assumption that if a sequence of nV masks is
28438fd1498Szrj    suitable for one (nS,nL) pair, we can reuse it for (nS/2,nL/2) by
28538fd1498Szrj    VIEW_CONVERTing it.  This holds for all current targets that support
28638fd1498Szrj    fully-masked loops.  For example, suppose the scalar loop is:
28738fd1498Szrj 
28838fd1498Szrj      float *f;
28938fd1498Szrj      double *d;
29038fd1498Szrj      for (int i = 0; i < n; ++i)
29138fd1498Szrj        {
29238fd1498Szrj 	 f[i * 2 + 0] += 1.0f;
29338fd1498Szrj 	 f[i * 2 + 1] += 2.0f;
29438fd1498Szrj 	 d[i] += 3.0;
29538fd1498Szrj        }
29638fd1498Szrj 
29738fd1498Szrj    and suppose that vectors have 256 bits.  The vectorized f accesses
29838fd1498Szrj    will belong to one rgroup and the vectorized d access to another:
29938fd1498Szrj 
30038fd1498Szrj      f rgroup: nS = 2, nV = 1, nL = 8
30138fd1498Szrj      d rgroup: nS = 1, nV = 1, nL = 4
30238fd1498Szrj 	       VF = 4
30338fd1498Szrj 
30438fd1498Szrj      [ In this simple example the rgroups do correspond to the normal
30538fd1498Szrj        SLP grouping scheme. ]
30638fd1498Szrj 
30738fd1498Szrj    If only the first three lanes are active, the masks we need are:
30838fd1498Szrj 
30938fd1498Szrj      f rgroup: 1 1 | 1 1 | 1 1 | 0 0
31038fd1498Szrj      d rgroup:  1  |  1  |  1  |  0
31138fd1498Szrj 
31238fd1498Szrj    Here we can use a mask calculated for f's rgroup for d's, but not
31338fd1498Szrj    vice versa.
31438fd1498Szrj 
31538fd1498Szrj    Thus for each value of nV, it is enough to provide nV masks, with the
31638fd1498Szrj    mask being calculated based on the highest nL (or, equivalently, based
31738fd1498Szrj    on the highest nS) required by any rgroup with that nV.  We therefore
31838fd1498Szrj    represent the entire collection of masks as a two-level table, with the
31938fd1498Szrj    first level being indexed by nV - 1 (since nV == 0 doesn't exist) and
32038fd1498Szrj    the second being indexed by the mask index 0 <= i < nV.  */
32138fd1498Szrj 
32238fd1498Szrj /* The masks needed by rgroups with nV vectors, according to the
32338fd1498Szrj    description above.  */
32438fd1498Szrj struct rgroup_masks {
32538fd1498Szrj   /* The largest nS for all rgroups that use these masks.  */
32638fd1498Szrj   unsigned int max_nscalars_per_iter;
32738fd1498Szrj 
32838fd1498Szrj   /* The type of mask to use, based on the highest nS recorded above.  */
32938fd1498Szrj   tree mask_type;
33038fd1498Szrj 
33138fd1498Szrj   /* A vector of nV masks, in iteration order.  */
33238fd1498Szrj   vec<tree> masks;
33338fd1498Szrj };
33438fd1498Szrj 
33538fd1498Szrj typedef auto_vec<rgroup_masks> vec_loop_masks;
33638fd1498Szrj 
33738fd1498Szrj /*-----------------------------------------------------------------*/
33838fd1498Szrj /* Info on vectorized loops.                                       */
33938fd1498Szrj /*-----------------------------------------------------------------*/
34038fd1498Szrj typedef struct _loop_vec_info : public vec_info {
34138fd1498Szrj   _loop_vec_info (struct loop *);
34238fd1498Szrj   ~_loop_vec_info ();
34338fd1498Szrj 
34438fd1498Szrj   /* The loop to which this info struct refers to.  */
34538fd1498Szrj   struct loop *loop;
34638fd1498Szrj 
34738fd1498Szrj   /* The loop basic blocks.  */
34838fd1498Szrj   basic_block *bbs;
34938fd1498Szrj 
35038fd1498Szrj   /* Number of latch executions.  */
35138fd1498Szrj   tree num_itersm1;
35238fd1498Szrj   /* Number of iterations.  */
35338fd1498Szrj   tree num_iters;
35438fd1498Szrj   /* Number of iterations of the original loop.  */
35538fd1498Szrj   tree num_iters_unchanged;
35638fd1498Szrj   /* Condition under which this loop is analyzed and versioned.  */
35738fd1498Szrj   tree num_iters_assumptions;
35838fd1498Szrj 
35938fd1498Szrj   /* Threshold of number of iterations below which vectorzation will not be
36038fd1498Szrj      performed. It is calculated from MIN_PROFITABLE_ITERS and
36138fd1498Szrj      PARAM_MIN_VECT_LOOP_BOUND.  */
36238fd1498Szrj   unsigned int th;
36338fd1498Szrj 
36438fd1498Szrj   /* When applying loop versioning, the vector form should only be used
36538fd1498Szrj      if the number of scalar iterations is >= this value, on top of all
36638fd1498Szrj      the other requirements.  Ignored when loop versioning is not being
36738fd1498Szrj      used.  */
36838fd1498Szrj   poly_uint64 versioning_threshold;
36938fd1498Szrj 
37038fd1498Szrj   /* Unrolling factor  */
37138fd1498Szrj   poly_uint64 vectorization_factor;
37238fd1498Szrj 
37338fd1498Szrj   /* Maximum runtime vectorization factor, or MAX_VECTORIZATION_FACTOR
37438fd1498Szrj      if there is no particular limit.  */
37538fd1498Szrj   unsigned HOST_WIDE_INT max_vectorization_factor;
37638fd1498Szrj 
37738fd1498Szrj   /* The masks that a fully-masked loop should use to avoid operating
37838fd1498Szrj      on inactive scalars.  */
37938fd1498Szrj   vec_loop_masks masks;
38038fd1498Szrj 
38138fd1498Szrj   /* If we are using a loop mask to align memory addresses, this variable
38238fd1498Szrj      contains the number of vector elements that we should skip in the
38338fd1498Szrj      first iteration of the vector loop (i.e. the number of leading
38438fd1498Szrj      elements that should be false in the first mask).  */
38538fd1498Szrj   tree mask_skip_niters;
38638fd1498Szrj 
38738fd1498Szrj   /* Type of the variables to use in the WHILE_ULT call for fully-masked
38838fd1498Szrj      loops.  */
38938fd1498Szrj   tree mask_compare_type;
39038fd1498Szrj 
39138fd1498Szrj   /* Unknown DRs according to which loop was peeled.  */
39238fd1498Szrj   struct data_reference *unaligned_dr;
39338fd1498Szrj 
39438fd1498Szrj   /* peeling_for_alignment indicates whether peeling for alignment will take
39538fd1498Szrj      place, and what the peeling factor should be:
39638fd1498Szrj      peeling_for_alignment = X means:
39738fd1498Szrj         If X=0: Peeling for alignment will not be applied.
39838fd1498Szrj         If X>0: Peel first X iterations.
39938fd1498Szrj         If X=-1: Generate a runtime test to calculate the number of iterations
40038fd1498Szrj                  to be peeled, using the dataref recorded in the field
40138fd1498Szrj                  unaligned_dr.  */
40238fd1498Szrj   int peeling_for_alignment;
40338fd1498Szrj 
40438fd1498Szrj   /* The mask used to check the alignment of pointers or arrays.  */
40538fd1498Szrj   int ptr_mask;
40638fd1498Szrj 
40738fd1498Szrj   /* The loop nest in which the data dependences are computed.  */
40838fd1498Szrj   auto_vec<loop_p> loop_nest;
40938fd1498Szrj 
41038fd1498Szrj   /* Data Dependence Relations defining address ranges that are candidates
41138fd1498Szrj      for a run-time aliasing check.  */
41238fd1498Szrj   auto_vec<ddr_p> may_alias_ddrs;
41338fd1498Szrj 
41438fd1498Szrj   /* Data Dependence Relations defining address ranges together with segment
41538fd1498Szrj      lengths from which the run-time aliasing check is built.  */
41638fd1498Szrj   auto_vec<dr_with_seg_len_pair_t> comp_alias_ddrs;
41738fd1498Szrj 
41838fd1498Szrj   /* Check that the addresses of each pair of objects is unequal.  */
41938fd1498Szrj   auto_vec<vec_object_pair> check_unequal_addrs;
42038fd1498Szrj 
42138fd1498Szrj   /* List of values that are required to be nonzero.  This is used to check
42238fd1498Szrj      whether things like "x[i * n] += 1;" are safe and eventually gets added
42338fd1498Szrj      to the checks for lower bounds below.  */
42438fd1498Szrj   auto_vec<tree> check_nonzero;
42538fd1498Szrj 
42638fd1498Szrj   /* List of values that need to be checked for a minimum value.  */
42738fd1498Szrj   auto_vec<vec_lower_bound> lower_bounds;
42838fd1498Szrj 
42938fd1498Szrj   /* Statements in the loop that have data references that are candidates for a
43038fd1498Szrj      runtime (loop versioning) misalignment check.  */
43138fd1498Szrj   auto_vec<gimple *> may_misalign_stmts;
43238fd1498Szrj 
43338fd1498Szrj   /* Reduction cycles detected in the loop. Used in loop-aware SLP.  */
43438fd1498Szrj   auto_vec<gimple *> reductions;
43538fd1498Szrj 
43638fd1498Szrj   /* All reduction chains in the loop, represented by the first
43738fd1498Szrj      stmt in the chain.  */
43838fd1498Szrj   auto_vec<gimple *> reduction_chains;
43938fd1498Szrj 
44038fd1498Szrj   /* Cost vector for a single scalar iteration.  */
44138fd1498Szrj   auto_vec<stmt_info_for_cost> scalar_cost_vec;
44238fd1498Szrj 
44338fd1498Szrj   /* Map of IV base/step expressions to inserted name in the preheader.  */
44438fd1498Szrj   hash_map<tree_operand_hash, tree> *ivexpr_map;
44538fd1498Szrj 
44638fd1498Szrj   /* The unrolling factor needed to SLP the loop. In case of that pure SLP is
44738fd1498Szrj      applied to the loop, i.e., no unrolling is needed, this is 1.  */
44838fd1498Szrj   poly_uint64 slp_unrolling_factor;
44938fd1498Szrj 
45038fd1498Szrj   /* Cost of a single scalar iteration.  */
45138fd1498Szrj   int single_scalar_iteration_cost;
45238fd1498Szrj 
45338fd1498Szrj   /* Is the loop vectorizable? */
45438fd1498Szrj   bool vectorizable;
45538fd1498Szrj 
45638fd1498Szrj   /* Records whether we still have the option of using a fully-masked loop.  */
45738fd1498Szrj   bool can_fully_mask_p;
45838fd1498Szrj 
45938fd1498Szrj   /* True if have decided to use a fully-masked loop.  */
46038fd1498Szrj   bool fully_masked_p;
46138fd1498Szrj 
46238fd1498Szrj   /* When we have grouped data accesses with gaps, we may introduce invalid
46338fd1498Szrj      memory accesses.  We peel the last iteration of the loop to prevent
46438fd1498Szrj      this.  */
46538fd1498Szrj   bool peeling_for_gaps;
46638fd1498Szrj 
46738fd1498Szrj   /* When the number of iterations is not a multiple of the vector size
46838fd1498Szrj      we need to peel off iterations at the end to form an epilogue loop.  */
46938fd1498Szrj   bool peeling_for_niter;
47038fd1498Szrj 
47138fd1498Szrj   /* Reductions are canonicalized so that the last operand is the reduction
47238fd1498Szrj      operand.  If this places a constant into RHS1, this decanonicalizes
47338fd1498Szrj      GIMPLE for other phases, so we must track when this has occurred and
47438fd1498Szrj      fix it up.  */
47538fd1498Szrj   bool operands_swapped;
47638fd1498Szrj 
47738fd1498Szrj   /* True if there are no loop carried data dependencies in the loop.
47838fd1498Szrj      If loop->safelen <= 1, then this is always true, either the loop
47938fd1498Szrj      didn't have any loop carried data dependencies, or the loop is being
48038fd1498Szrj      vectorized guarded with some runtime alias checks, or couldn't
48138fd1498Szrj      be vectorized at all, but then this field shouldn't be used.
48238fd1498Szrj      For loop->safelen >= 2, the user has asserted that there are no
48338fd1498Szrj      backward dependencies, but there still could be loop carried forward
48438fd1498Szrj      dependencies in such loops.  This flag will be false if normal
48538fd1498Szrj      vectorizer data dependency analysis would fail or require versioning
48638fd1498Szrj      for alias, but because of loop->safelen >= 2 it has been vectorized
48738fd1498Szrj      even without versioning for alias.  E.g. in:
48838fd1498Szrj      #pragma omp simd
48938fd1498Szrj      for (int i = 0; i < m; i++)
49038fd1498Szrj        a[i] = a[i + k] * c;
49138fd1498Szrj      (or #pragma simd or #pragma ivdep) we can vectorize this and it will
49238fd1498Szrj      DTRT even for k > 0 && k < m, but without safelen we would not
49338fd1498Szrj      vectorize this, so this field would be false.  */
49438fd1498Szrj   bool no_data_dependencies;
49538fd1498Szrj 
49638fd1498Szrj   /* Mark loops having masked stores.  */
49738fd1498Szrj   bool has_mask_store;
49838fd1498Szrj 
49938fd1498Szrj   /* If if-conversion versioned this loop before conversion, this is the
50038fd1498Szrj      loop version without if-conversion.  */
50138fd1498Szrj   struct loop *scalar_loop;
50238fd1498Szrj 
50338fd1498Szrj   /* For loops being epilogues of already vectorized loops
50438fd1498Szrj      this points to the original vectorized loop.  Otherwise NULL.  */
50538fd1498Szrj   _loop_vec_info *orig_loop_info;
50638fd1498Szrj 
50738fd1498Szrj } *loop_vec_info;
50838fd1498Szrj 
50938fd1498Szrj /* Access Functions.  */
51038fd1498Szrj #define LOOP_VINFO_LOOP(L)                 (L)->loop
51138fd1498Szrj #define LOOP_VINFO_BBS(L)                  (L)->bbs
51238fd1498Szrj #define LOOP_VINFO_NITERSM1(L)             (L)->num_itersm1
51338fd1498Szrj #define LOOP_VINFO_NITERS(L)               (L)->num_iters
51438fd1498Szrj /* Since LOOP_VINFO_NITERS and LOOP_VINFO_NITERSM1 can change after
51538fd1498Szrj    prologue peeling retain total unchanged scalar loop iterations for
51638fd1498Szrj    cost model.  */
51738fd1498Szrj #define LOOP_VINFO_NITERS_UNCHANGED(L)     (L)->num_iters_unchanged
51838fd1498Szrj #define LOOP_VINFO_NITERS_ASSUMPTIONS(L)   (L)->num_iters_assumptions
51938fd1498Szrj #define LOOP_VINFO_COST_MODEL_THRESHOLD(L) (L)->th
52038fd1498Szrj #define LOOP_VINFO_VERSIONING_THRESHOLD(L) (L)->versioning_threshold
52138fd1498Szrj #define LOOP_VINFO_VECTORIZABLE_P(L)       (L)->vectorizable
52238fd1498Szrj #define LOOP_VINFO_CAN_FULLY_MASK_P(L)     (L)->can_fully_mask_p
52338fd1498Szrj #define LOOP_VINFO_FULLY_MASKED_P(L)       (L)->fully_masked_p
52438fd1498Szrj #define LOOP_VINFO_VECT_FACTOR(L)          (L)->vectorization_factor
52538fd1498Szrj #define LOOP_VINFO_MAX_VECT_FACTOR(L)      (L)->max_vectorization_factor
52638fd1498Szrj #define LOOP_VINFO_MASKS(L)                (L)->masks
52738fd1498Szrj #define LOOP_VINFO_MASK_SKIP_NITERS(L)     (L)->mask_skip_niters
52838fd1498Szrj #define LOOP_VINFO_MASK_COMPARE_TYPE(L)    (L)->mask_compare_type
52938fd1498Szrj #define LOOP_VINFO_PTR_MASK(L)             (L)->ptr_mask
53038fd1498Szrj #define LOOP_VINFO_LOOP_NEST(L)            (L)->loop_nest
53138fd1498Szrj #define LOOP_VINFO_DATAREFS(L)             (L)->datarefs
53238fd1498Szrj #define LOOP_VINFO_DDRS(L)                 (L)->ddrs
53338fd1498Szrj #define LOOP_VINFO_INT_NITERS(L)           (TREE_INT_CST_LOW ((L)->num_iters))
53438fd1498Szrj #define LOOP_VINFO_PEELING_FOR_ALIGNMENT(L) (L)->peeling_for_alignment
53538fd1498Szrj #define LOOP_VINFO_UNALIGNED_DR(L)         (L)->unaligned_dr
53638fd1498Szrj #define LOOP_VINFO_MAY_MISALIGN_STMTS(L)   (L)->may_misalign_stmts
53738fd1498Szrj #define LOOP_VINFO_MAY_ALIAS_DDRS(L)       (L)->may_alias_ddrs
53838fd1498Szrj #define LOOP_VINFO_COMP_ALIAS_DDRS(L)      (L)->comp_alias_ddrs
53938fd1498Szrj #define LOOP_VINFO_CHECK_UNEQUAL_ADDRS(L)  (L)->check_unequal_addrs
54038fd1498Szrj #define LOOP_VINFO_CHECK_NONZERO(L)        (L)->check_nonzero
54138fd1498Szrj #define LOOP_VINFO_LOWER_BOUNDS(L)         (L)->lower_bounds
54238fd1498Szrj #define LOOP_VINFO_GROUPED_STORES(L)       (L)->grouped_stores
54338fd1498Szrj #define LOOP_VINFO_SLP_INSTANCES(L)        (L)->slp_instances
54438fd1498Szrj #define LOOP_VINFO_SLP_UNROLLING_FACTOR(L) (L)->slp_unrolling_factor
54538fd1498Szrj #define LOOP_VINFO_REDUCTIONS(L)           (L)->reductions
54638fd1498Szrj #define LOOP_VINFO_REDUCTION_CHAINS(L)     (L)->reduction_chains
54738fd1498Szrj #define LOOP_VINFO_TARGET_COST_DATA(L)     (L)->target_cost_data
54838fd1498Szrj #define LOOP_VINFO_PEELING_FOR_GAPS(L)     (L)->peeling_for_gaps
54938fd1498Szrj #define LOOP_VINFO_OPERANDS_SWAPPED(L)     (L)->operands_swapped
55038fd1498Szrj #define LOOP_VINFO_PEELING_FOR_NITER(L)    (L)->peeling_for_niter
55138fd1498Szrj #define LOOP_VINFO_NO_DATA_DEPENDENCIES(L) (L)->no_data_dependencies
55238fd1498Szrj #define LOOP_VINFO_SCALAR_LOOP(L)	   (L)->scalar_loop
55338fd1498Szrj #define LOOP_VINFO_HAS_MASK_STORE(L)       (L)->has_mask_store
55438fd1498Szrj #define LOOP_VINFO_SCALAR_ITERATION_COST(L) (L)->scalar_cost_vec
55538fd1498Szrj #define LOOP_VINFO_SINGLE_SCALAR_ITERATION_COST(L) (L)->single_scalar_iteration_cost
55638fd1498Szrj #define LOOP_VINFO_ORIG_LOOP_INFO(L)       (L)->orig_loop_info
55738fd1498Szrj 
55838fd1498Szrj #define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L)	\
55938fd1498Szrj   ((L)->may_misalign_stmts.length () > 0)
56038fd1498Szrj #define LOOP_REQUIRES_VERSIONING_FOR_ALIAS(L)		\
56138fd1498Szrj   ((L)->comp_alias_ddrs.length () > 0 \
56238fd1498Szrj    || (L)->check_unequal_addrs.length () > 0 \
56338fd1498Szrj    || (L)->lower_bounds.length () > 0)
56438fd1498Szrj #define LOOP_REQUIRES_VERSIONING_FOR_NITERS(L)		\
56538fd1498Szrj   (LOOP_VINFO_NITERS_ASSUMPTIONS (L))
56638fd1498Szrj #define LOOP_REQUIRES_VERSIONING(L)			\
56738fd1498Szrj   (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (L)		\
56838fd1498Szrj    || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (L)		\
56938fd1498Szrj    || LOOP_REQUIRES_VERSIONING_FOR_NITERS (L))
57038fd1498Szrj 
57138fd1498Szrj #define LOOP_VINFO_NITERS_KNOWN_P(L)          \
57238fd1498Szrj   (tree_fits_shwi_p ((L)->num_iters) && tree_to_shwi ((L)->num_iters) > 0)
57338fd1498Szrj 
57438fd1498Szrj #define LOOP_VINFO_EPILOGUE_P(L) \
57538fd1498Szrj   (LOOP_VINFO_ORIG_LOOP_INFO (L) != NULL)
57638fd1498Szrj 
57738fd1498Szrj #define LOOP_VINFO_ORIG_MAX_VECT_FACTOR(L) \
57838fd1498Szrj   (LOOP_VINFO_MAX_VECT_FACTOR (LOOP_VINFO_ORIG_LOOP_INFO (L)))
57938fd1498Szrj 
58038fd1498Szrj static inline loop_vec_info
loop_vec_info_for_loop(struct loop * loop)58138fd1498Szrj loop_vec_info_for_loop (struct loop *loop)
58238fd1498Szrj {
58338fd1498Szrj   return (loop_vec_info) loop->aux;
58438fd1498Szrj }
58538fd1498Szrj 
58638fd1498Szrj static inline bool
nested_in_vect_loop_p(struct loop * loop,gimple * stmt)58738fd1498Szrj nested_in_vect_loop_p (struct loop *loop, gimple *stmt)
58838fd1498Szrj {
58938fd1498Szrj   return (loop->inner
59038fd1498Szrj           && (loop->inner == (gimple_bb (stmt))->loop_father));
59138fd1498Szrj }
59238fd1498Szrj 
59338fd1498Szrj typedef struct _bb_vec_info : public vec_info
59438fd1498Szrj {
59538fd1498Szrj   _bb_vec_info (gimple_stmt_iterator, gimple_stmt_iterator);
59638fd1498Szrj   ~_bb_vec_info ();
59738fd1498Szrj 
59838fd1498Szrj   basic_block bb;
59938fd1498Szrj   gimple_stmt_iterator region_begin;
60038fd1498Szrj   gimple_stmt_iterator region_end;
60138fd1498Szrj } *bb_vec_info;
60238fd1498Szrj 
60338fd1498Szrj #define BB_VINFO_BB(B)               (B)->bb
60438fd1498Szrj #define BB_VINFO_GROUPED_STORES(B)   (B)->grouped_stores
60538fd1498Szrj #define BB_VINFO_SLP_INSTANCES(B)    (B)->slp_instances
60638fd1498Szrj #define BB_VINFO_DATAREFS(B)         (B)->datarefs
60738fd1498Szrj #define BB_VINFO_DDRS(B)             (B)->ddrs
60838fd1498Szrj #define BB_VINFO_TARGET_COST_DATA(B) (B)->target_cost_data
60938fd1498Szrj 
61038fd1498Szrj static inline bb_vec_info
vec_info_for_bb(basic_block bb)61138fd1498Szrj vec_info_for_bb (basic_block bb)
61238fd1498Szrj {
61338fd1498Szrj   return (bb_vec_info) bb->aux;
61438fd1498Szrj }
61538fd1498Szrj 
61638fd1498Szrj /*-----------------------------------------------------------------*/
61738fd1498Szrj /* Info on vectorized defs.                                        */
61838fd1498Szrj /*-----------------------------------------------------------------*/
61938fd1498Szrj enum stmt_vec_info_type {
62038fd1498Szrj   undef_vec_info_type = 0,
62138fd1498Szrj   load_vec_info_type,
62238fd1498Szrj   store_vec_info_type,
62338fd1498Szrj   shift_vec_info_type,
62438fd1498Szrj   op_vec_info_type,
62538fd1498Szrj   call_vec_info_type,
62638fd1498Szrj   call_simd_clone_vec_info_type,
62738fd1498Szrj   assignment_vec_info_type,
62838fd1498Szrj   condition_vec_info_type,
62938fd1498Szrj   comparison_vec_info_type,
63038fd1498Szrj   reduc_vec_info_type,
63138fd1498Szrj   induc_vec_info_type,
63238fd1498Szrj   type_promotion_vec_info_type,
63338fd1498Szrj   type_demotion_vec_info_type,
63438fd1498Szrj   type_conversion_vec_info_type,
63538fd1498Szrj   loop_exit_ctrl_vec_info_type
63638fd1498Szrj };
63738fd1498Szrj 
63838fd1498Szrj /* Indicates whether/how a variable is used in the scope of loop/basic
63938fd1498Szrj    block.  */
64038fd1498Szrj enum vect_relevant {
64138fd1498Szrj   vect_unused_in_scope = 0,
64238fd1498Szrj 
64338fd1498Szrj   /* The def is only used outside the loop.  */
64438fd1498Szrj   vect_used_only_live,
64538fd1498Szrj   /* The def is in the inner loop, and the use is in the outer loop, and the
64638fd1498Szrj      use is a reduction stmt.  */
64738fd1498Szrj   vect_used_in_outer_by_reduction,
64838fd1498Szrj   /* The def is in the inner loop, and the use is in the outer loop (and is
64938fd1498Szrj      not part of reduction).  */
65038fd1498Szrj   vect_used_in_outer,
65138fd1498Szrj 
65238fd1498Szrj   /* defs that feed computations that end up (only) in a reduction. These
65338fd1498Szrj      defs may be used by non-reduction stmts, but eventually, any
65438fd1498Szrj      computations/values that are affected by these defs are used to compute
65538fd1498Szrj      a reduction (i.e. don't get stored to memory, for example). We use this
65638fd1498Szrj      to identify computations that we can change the order in which they are
65738fd1498Szrj      computed.  */
65838fd1498Szrj   vect_used_by_reduction,
65938fd1498Szrj 
66038fd1498Szrj   vect_used_in_scope
66138fd1498Szrj };
66238fd1498Szrj 
66338fd1498Szrj /* The type of vectorization that can be applied to the stmt: regular loop-based
66438fd1498Szrj    vectorization; pure SLP - the stmt is a part of SLP instances and does not
66538fd1498Szrj    have uses outside SLP instances; or hybrid SLP and loop-based - the stmt is
66638fd1498Szrj    a part of SLP instance and also must be loop-based vectorized, since it has
66738fd1498Szrj    uses outside SLP sequences.
66838fd1498Szrj 
66938fd1498Szrj    In the loop context the meanings of pure and hybrid SLP are slightly
67038fd1498Szrj    different. By saying that pure SLP is applied to the loop, we mean that we
67138fd1498Szrj    exploit only intra-iteration parallelism in the loop; i.e., the loop can be
67238fd1498Szrj    vectorized without doing any conceptual unrolling, cause we don't pack
67338fd1498Szrj    together stmts from different iterations, only within a single iteration.
67438fd1498Szrj    Loop hybrid SLP means that we exploit both intra-iteration and
67538fd1498Szrj    inter-iteration parallelism (e.g., number of elements in the vector is 4
67638fd1498Szrj    and the slp-group-size is 2, in which case we don't have enough parallelism
67738fd1498Szrj    within an iteration, so we obtain the rest of the parallelism from subsequent
67838fd1498Szrj    iterations by unrolling the loop by 2).  */
67938fd1498Szrj enum slp_vect_type {
68038fd1498Szrj   loop_vect = 0,
68138fd1498Szrj   pure_slp,
68238fd1498Szrj   hybrid
68338fd1498Szrj };
68438fd1498Szrj 
68538fd1498Szrj /* Says whether a statement is a load, a store of a vectorized statement
68638fd1498Szrj    result, or a store of an invariant value.  */
68738fd1498Szrj enum vec_load_store_type {
68838fd1498Szrj   VLS_LOAD,
68938fd1498Szrj   VLS_STORE,
69038fd1498Szrj   VLS_STORE_INVARIANT
69138fd1498Szrj };
69238fd1498Szrj 
69338fd1498Szrj /* Describes how we're going to vectorize an individual load or store,
69438fd1498Szrj    or a group of loads or stores.  */
69538fd1498Szrj enum vect_memory_access_type {
69638fd1498Szrj   /* An access to an invariant address.  This is used only for loads.  */
69738fd1498Szrj   VMAT_INVARIANT,
69838fd1498Szrj 
69938fd1498Szrj   /* A simple contiguous access.  */
70038fd1498Szrj   VMAT_CONTIGUOUS,
70138fd1498Szrj 
70238fd1498Szrj   /* A contiguous access that goes down in memory rather than up,
70338fd1498Szrj      with no additional permutation.  This is used only for stores
70438fd1498Szrj      of invariants.  */
70538fd1498Szrj   VMAT_CONTIGUOUS_DOWN,
70638fd1498Szrj 
70738fd1498Szrj   /* A simple contiguous access in which the elements need to be permuted
70838fd1498Szrj      after loading or before storing.  Only used for loop vectorization;
70938fd1498Szrj      SLP uses separate permutes.  */
71038fd1498Szrj   VMAT_CONTIGUOUS_PERMUTE,
71138fd1498Szrj 
71238fd1498Szrj   /* A simple contiguous access in which the elements need to be reversed
71338fd1498Szrj      after loading or before storing.  */
71438fd1498Szrj   VMAT_CONTIGUOUS_REVERSE,
71538fd1498Szrj 
71638fd1498Szrj   /* An access that uses IFN_LOAD_LANES or IFN_STORE_LANES.  */
71738fd1498Szrj   VMAT_LOAD_STORE_LANES,
71838fd1498Szrj 
71938fd1498Szrj   /* An access in which each scalar element is loaded or stored
72038fd1498Szrj      individually.  */
72138fd1498Szrj   VMAT_ELEMENTWISE,
72238fd1498Szrj 
72338fd1498Szrj   /* A hybrid of VMAT_CONTIGUOUS and VMAT_ELEMENTWISE, used for grouped
72438fd1498Szrj      SLP accesses.  Each unrolled iteration uses a contiguous load
72538fd1498Szrj      or store for the whole group, but the groups from separate iterations
72638fd1498Szrj      are combined in the same way as for VMAT_ELEMENTWISE.  */
72738fd1498Szrj   VMAT_STRIDED_SLP,
72838fd1498Szrj 
72938fd1498Szrj   /* The access uses gather loads or scatter stores.  */
73038fd1498Szrj   VMAT_GATHER_SCATTER
73138fd1498Szrj };
73238fd1498Szrj 
73338fd1498Szrj typedef struct data_reference *dr_p;
73438fd1498Szrj 
73538fd1498Szrj typedef struct _stmt_vec_info {
73638fd1498Szrj 
73738fd1498Szrj   enum stmt_vec_info_type type;
73838fd1498Szrj 
73938fd1498Szrj   /* Indicates whether this stmts is part of a computation whose result is
74038fd1498Szrj      used outside the loop.  */
74138fd1498Szrj   bool live;
74238fd1498Szrj 
74338fd1498Szrj   /* Stmt is part of some pattern (computation idiom)  */
74438fd1498Szrj   bool in_pattern_p;
74538fd1498Szrj 
74638fd1498Szrj   /* Is this statement vectorizable or should it be skipped in (partial)
74738fd1498Szrj      vectorization.  */
74838fd1498Szrj   bool vectorizable;
74938fd1498Szrj 
75038fd1498Szrj   /* The stmt to which this info struct refers to.  */
75138fd1498Szrj   gimple *stmt;
75238fd1498Szrj 
75338fd1498Szrj   /* The vec_info with respect to which STMT is vectorized.  */
75438fd1498Szrj   vec_info *vinfo;
75538fd1498Szrj 
75638fd1498Szrj   /* The vector type to be used for the LHS of this statement.  */
75738fd1498Szrj   tree vectype;
75838fd1498Szrj 
75938fd1498Szrj   /* The vectorized version of the stmt.  */
76038fd1498Szrj   gimple *vectorized_stmt;
76138fd1498Szrj 
76238fd1498Szrj 
76338fd1498Szrj   /* The following is relevant only for stmts that contain a non-scalar
76438fd1498Szrj      data-ref (array/pointer/struct access). A GIMPLE stmt is expected to have
76538fd1498Szrj      at most one such data-ref.  */
76638fd1498Szrj 
76738fd1498Szrj   /* Information about the data-ref (access function, etc),
76838fd1498Szrj      relative to the inner-most containing loop.  */
76938fd1498Szrj   struct data_reference *data_ref_info;
77038fd1498Szrj 
77138fd1498Szrj   /* Information about the data-ref relative to this loop
77238fd1498Szrj      nest (the loop that is being considered for vectorization).  */
77338fd1498Szrj   innermost_loop_behavior dr_wrt_vec_loop;
77438fd1498Szrj 
77538fd1498Szrj   /* For loop PHI nodes, the base and evolution part of it.  This makes sure
77638fd1498Szrj      this information is still available in vect_update_ivs_after_vectorizer
77738fd1498Szrj      where we may not be able to re-analyze the PHI nodes evolution as
77838fd1498Szrj      peeling for the prologue loop can make it unanalyzable.  The evolution
77938fd1498Szrj      part is still correct after peeling, but the base may have changed from
78038fd1498Szrj      the version here.  */
78138fd1498Szrj   tree loop_phi_evolution_base_unchanged;
78238fd1498Szrj   tree loop_phi_evolution_part;
78338fd1498Szrj 
78438fd1498Szrj   /* Used for various bookkeeping purposes, generally holding a pointer to
78538fd1498Szrj      some other stmt S that is in some way "related" to this stmt.
78638fd1498Szrj      Current use of this field is:
78738fd1498Szrj         If this stmt is part of a pattern (i.e. the field 'in_pattern_p' is
78838fd1498Szrj         true): S is the "pattern stmt" that represents (and replaces) the
78938fd1498Szrj         sequence of stmts that constitutes the pattern.  Similarly, the
79038fd1498Szrj         related_stmt of the "pattern stmt" points back to this stmt (which is
79138fd1498Szrj         the last stmt in the original sequence of stmts that constitutes the
79238fd1498Szrj         pattern).  */
79338fd1498Szrj   gimple *related_stmt;
79438fd1498Szrj 
79538fd1498Szrj   /* Used to keep a sequence of def stmts of a pattern stmt if such exists.  */
79638fd1498Szrj   gimple_seq pattern_def_seq;
79738fd1498Szrj 
79838fd1498Szrj   /* List of datarefs that are known to have the same alignment as the dataref
79938fd1498Szrj      of this stmt.  */
80038fd1498Szrj   vec<dr_p> same_align_refs;
80138fd1498Szrj 
80238fd1498Szrj   /* Selected SIMD clone's function info.  First vector element
80338fd1498Szrj      is SIMD clone's function decl, followed by a pair of trees (base + step)
80438fd1498Szrj      for linear arguments (pair of NULLs for other arguments).  */
80538fd1498Szrj   vec<tree> simd_clone_info;
80638fd1498Szrj 
80738fd1498Szrj   /* Classify the def of this stmt.  */
80838fd1498Szrj   enum vect_def_type def_type;
80938fd1498Szrj 
81038fd1498Szrj   /*  Whether the stmt is SLPed, loop-based vectorized, or both.  */
81138fd1498Szrj   enum slp_vect_type slp_type;
81238fd1498Szrj 
81338fd1498Szrj   /* Interleaving and reduction chains info.  */
81438fd1498Szrj   /* First element in the group.  */
81538fd1498Szrj   gimple *first_element;
81638fd1498Szrj   /* Pointer to the next element in the group.  */
81738fd1498Szrj   gimple *next_element;
81838fd1498Szrj   /* For data-refs, in case that two or more stmts share data-ref, this is the
81938fd1498Szrj      pointer to the previously detected stmt with the same dr.  */
82038fd1498Szrj   gimple *same_dr_stmt;
82138fd1498Szrj   /* The size of the group.  */
82238fd1498Szrj   unsigned int size;
82338fd1498Szrj   /* For stores, number of stores from this group seen. We vectorize the last
82438fd1498Szrj      one.  */
82538fd1498Szrj   unsigned int store_count;
82638fd1498Szrj   /* For loads only, the gap from the previous load. For consecutive loads, GAP
82738fd1498Szrj      is 1.  */
82838fd1498Szrj   unsigned int gap;
82938fd1498Szrj 
83038fd1498Szrj   /* The minimum negative dependence distance this stmt participates in
83138fd1498Szrj      or zero if none.  */
83238fd1498Szrj   unsigned int min_neg_dist;
83338fd1498Szrj 
83438fd1498Szrj   /* Not all stmts in the loop need to be vectorized. e.g, the increment
83538fd1498Szrj      of the loop induction variable and computation of array indexes. relevant
83638fd1498Szrj      indicates whether the stmt needs to be vectorized.  */
83738fd1498Szrj   enum vect_relevant relevant;
83838fd1498Szrj 
83938fd1498Szrj   /* For loads if this is a gather, for stores if this is a scatter.  */
84038fd1498Szrj   bool gather_scatter_p;
84138fd1498Szrj 
84238fd1498Szrj   /* True if this is an access with loop-invariant stride.  */
84338fd1498Szrj   bool strided_p;
84438fd1498Szrj 
84538fd1498Szrj   /* For both loads and stores.  */
84638fd1498Szrj   bool simd_lane_access_p;
84738fd1498Szrj 
84838fd1498Szrj   /* Classifies how the load or store is going to be implemented
84938fd1498Szrj      for loop vectorization.  */
85038fd1498Szrj   vect_memory_access_type memory_access_type;
85138fd1498Szrj 
85238fd1498Szrj   /* For reduction loops, this is the type of reduction.  */
85338fd1498Szrj   enum vect_reduction_type v_reduc_type;
85438fd1498Szrj 
85538fd1498Szrj   /* For CONST_COND_REDUCTION, record the reduc code.  */
85638fd1498Szrj   enum tree_code const_cond_reduc_code;
85738fd1498Szrj 
85838fd1498Szrj   /* On a reduction PHI the reduction type as detected by
85938fd1498Szrj      vect_force_simple_reduction.  */
86038fd1498Szrj   enum vect_reduction_type reduc_type;
86138fd1498Szrj 
86238fd1498Szrj   /* On a reduction PHI the def returned by vect_force_simple_reduction.
86338fd1498Szrj      On the def returned by vect_force_simple_reduction the
86438fd1498Szrj      corresponding PHI.  */
86538fd1498Szrj   gimple *reduc_def;
86638fd1498Szrj 
86738fd1498Szrj   /* The number of scalar stmt references from active SLP instances.  */
86838fd1498Szrj   unsigned int num_slp_uses;
86938fd1498Szrj } *stmt_vec_info;
87038fd1498Szrj 
87138fd1498Szrj /* Information about a gather/scatter call.  */
87238fd1498Szrj struct gather_scatter_info {
87338fd1498Szrj   /* The internal function to use for the gather/scatter operation,
87438fd1498Szrj      or IFN_LAST if a built-in function should be used instead.  */
87538fd1498Szrj   internal_fn ifn;
87638fd1498Szrj 
87738fd1498Szrj   /* The FUNCTION_DECL for the built-in gather/scatter function,
87838fd1498Szrj      or null if an internal function should be used instead.  */
87938fd1498Szrj   tree decl;
88038fd1498Szrj 
88138fd1498Szrj   /* The loop-invariant base value.  */
88238fd1498Szrj   tree base;
88338fd1498Szrj 
88438fd1498Szrj   /* The original scalar offset, which is a non-loop-invariant SSA_NAME.  */
88538fd1498Szrj   tree offset;
88638fd1498Szrj 
88738fd1498Szrj   /* Each offset element should be multiplied by this amount before
88838fd1498Szrj      being added to the base.  */
88938fd1498Szrj   int scale;
89038fd1498Szrj 
89138fd1498Szrj   /* The definition type for the vectorized offset.  */
89238fd1498Szrj   enum vect_def_type offset_dt;
89338fd1498Szrj 
89438fd1498Szrj   /* The type of the vectorized offset.  */
89538fd1498Szrj   tree offset_vectype;
89638fd1498Szrj 
89738fd1498Szrj   /* The type of the scalar elements after loading or before storing.  */
89838fd1498Szrj   tree element_type;
89938fd1498Szrj 
90038fd1498Szrj   /* The type of the scalar elements being loaded or stored.  */
90138fd1498Szrj   tree memory_type;
90238fd1498Szrj };
90338fd1498Szrj 
90438fd1498Szrj /* Access Functions.  */
90538fd1498Szrj #define STMT_VINFO_TYPE(S)                 (S)->type
90638fd1498Szrj #define STMT_VINFO_STMT(S)                 (S)->stmt
90738fd1498Szrj inline loop_vec_info
STMT_VINFO_LOOP_VINFO(stmt_vec_info stmt_vinfo)90838fd1498Szrj STMT_VINFO_LOOP_VINFO (stmt_vec_info stmt_vinfo)
90938fd1498Szrj {
91038fd1498Szrj   if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (stmt_vinfo->vinfo))
91138fd1498Szrj     return loop_vinfo;
91238fd1498Szrj   return NULL;
91338fd1498Szrj }
91438fd1498Szrj inline bb_vec_info
STMT_VINFO_BB_VINFO(stmt_vec_info stmt_vinfo)91538fd1498Szrj STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
91638fd1498Szrj {
91738fd1498Szrj   if (bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (stmt_vinfo->vinfo))
91838fd1498Szrj     return bb_vinfo;
91938fd1498Szrj   return NULL;
92038fd1498Szrj }
92138fd1498Szrj #define STMT_VINFO_RELEVANT(S)             (S)->relevant
92238fd1498Szrj #define STMT_VINFO_LIVE_P(S)               (S)->live
92338fd1498Szrj #define STMT_VINFO_VECTYPE(S)              (S)->vectype
92438fd1498Szrj #define STMT_VINFO_VEC_STMT(S)             (S)->vectorized_stmt
92538fd1498Szrj #define STMT_VINFO_VECTORIZABLE(S)         (S)->vectorizable
92638fd1498Szrj #define STMT_VINFO_DATA_REF(S)             (S)->data_ref_info
92738fd1498Szrj #define STMT_VINFO_GATHER_SCATTER_P(S)	   (S)->gather_scatter_p
92838fd1498Szrj #define STMT_VINFO_STRIDED_P(S)	   	   (S)->strided_p
92938fd1498Szrj #define STMT_VINFO_MEMORY_ACCESS_TYPE(S)   (S)->memory_access_type
93038fd1498Szrj #define STMT_VINFO_SIMD_LANE_ACCESS_P(S)   (S)->simd_lane_access_p
93138fd1498Szrj #define STMT_VINFO_VEC_REDUCTION_TYPE(S)   (S)->v_reduc_type
93238fd1498Szrj #define STMT_VINFO_VEC_CONST_COND_REDUC_CODE(S) (S)->const_cond_reduc_code
93338fd1498Szrj 
93438fd1498Szrj #define STMT_VINFO_DR_WRT_VEC_LOOP(S)      (S)->dr_wrt_vec_loop
93538fd1498Szrj #define STMT_VINFO_DR_BASE_ADDRESS(S)      (S)->dr_wrt_vec_loop.base_address
93638fd1498Szrj #define STMT_VINFO_DR_INIT(S)              (S)->dr_wrt_vec_loop.init
93738fd1498Szrj #define STMT_VINFO_DR_OFFSET(S)            (S)->dr_wrt_vec_loop.offset
93838fd1498Szrj #define STMT_VINFO_DR_STEP(S)              (S)->dr_wrt_vec_loop.step
93938fd1498Szrj #define STMT_VINFO_DR_BASE_ALIGNMENT(S)    (S)->dr_wrt_vec_loop.base_alignment
94038fd1498Szrj #define STMT_VINFO_DR_BASE_MISALIGNMENT(S) \
94138fd1498Szrj   (S)->dr_wrt_vec_loop.base_misalignment
94238fd1498Szrj #define STMT_VINFO_DR_OFFSET_ALIGNMENT(S) \
94338fd1498Szrj   (S)->dr_wrt_vec_loop.offset_alignment
94438fd1498Szrj #define STMT_VINFO_DR_STEP_ALIGNMENT(S) \
94538fd1498Szrj   (S)->dr_wrt_vec_loop.step_alignment
94638fd1498Szrj 
94738fd1498Szrj #define STMT_VINFO_IN_PATTERN_P(S)         (S)->in_pattern_p
94838fd1498Szrj #define STMT_VINFO_RELATED_STMT(S)         (S)->related_stmt
94938fd1498Szrj #define STMT_VINFO_PATTERN_DEF_SEQ(S)      (S)->pattern_def_seq
95038fd1498Szrj #define STMT_VINFO_SAME_ALIGN_REFS(S)      (S)->same_align_refs
95138fd1498Szrj #define STMT_VINFO_SIMD_CLONE_INFO(S)	   (S)->simd_clone_info
95238fd1498Szrj #define STMT_VINFO_DEF_TYPE(S)             (S)->def_type
95338fd1498Szrj #define STMT_VINFO_GROUP_FIRST_ELEMENT(S)  (S)->first_element
95438fd1498Szrj #define STMT_VINFO_GROUP_NEXT_ELEMENT(S)   (S)->next_element
95538fd1498Szrj #define STMT_VINFO_GROUP_SIZE(S)           (S)->size
95638fd1498Szrj #define STMT_VINFO_GROUP_STORE_COUNT(S)    (S)->store_count
95738fd1498Szrj #define STMT_VINFO_GROUP_GAP(S)            (S)->gap
95838fd1498Szrj #define STMT_VINFO_GROUP_SAME_DR_STMT(S)   (S)->same_dr_stmt
95938fd1498Szrj #define STMT_VINFO_GROUPED_ACCESS(S)      ((S)->first_element != NULL && (S)->data_ref_info)
96038fd1498Szrj #define STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED(S) (S)->loop_phi_evolution_base_unchanged
96138fd1498Szrj #define STMT_VINFO_LOOP_PHI_EVOLUTION_PART(S) (S)->loop_phi_evolution_part
96238fd1498Szrj #define STMT_VINFO_MIN_NEG_DIST(S)	(S)->min_neg_dist
96338fd1498Szrj #define STMT_VINFO_NUM_SLP_USES(S)	(S)->num_slp_uses
96438fd1498Szrj #define STMT_VINFO_REDUC_TYPE(S)	(S)->reduc_type
96538fd1498Szrj #define STMT_VINFO_REDUC_DEF(S)		(S)->reduc_def
96638fd1498Szrj 
96738fd1498Szrj #define GROUP_FIRST_ELEMENT(S)          (S)->first_element
96838fd1498Szrj #define GROUP_NEXT_ELEMENT(S)           (S)->next_element
96938fd1498Szrj #define GROUP_SIZE(S)                   (S)->size
97038fd1498Szrj #define GROUP_STORE_COUNT(S)            (S)->store_count
97138fd1498Szrj #define GROUP_GAP(S)                    (S)->gap
97238fd1498Szrj #define GROUP_SAME_DR_STMT(S)           (S)->same_dr_stmt
97338fd1498Szrj 
97438fd1498Szrj #define STMT_VINFO_RELEVANT_P(S)          ((S)->relevant != vect_unused_in_scope)
97538fd1498Szrj 
97638fd1498Szrj #define HYBRID_SLP_STMT(S)                ((S)->slp_type == hybrid)
97738fd1498Szrj #define PURE_SLP_STMT(S)                  ((S)->slp_type == pure_slp)
97838fd1498Szrj #define STMT_SLP_TYPE(S)                   (S)->slp_type
97938fd1498Szrj 
98038fd1498Szrj struct dataref_aux {
98138fd1498Szrj   /* The misalignment in bytes of the reference, or -1 if not known.  */
98238fd1498Szrj   int misalignment;
98338fd1498Szrj   /* The byte alignment that we'd ideally like the reference to have,
98438fd1498Szrj      and the value that misalignment is measured against.  */
98538fd1498Szrj   int target_alignment;
98638fd1498Szrj   /* If true the alignment of base_decl needs to be increased.  */
98738fd1498Szrj   bool base_misaligned;
98838fd1498Szrj   tree base_decl;
98938fd1498Szrj };
99038fd1498Szrj 
99138fd1498Szrj #define DR_VECT_AUX(dr) ((dataref_aux *)(dr)->aux)
99238fd1498Szrj 
99338fd1498Szrj #define VECT_MAX_COST 1000
99438fd1498Szrj 
99538fd1498Szrj /* The maximum number of intermediate steps required in multi-step type
99638fd1498Szrj    conversion.  */
99738fd1498Szrj #define MAX_INTERM_CVT_STEPS         3
99838fd1498Szrj 
99938fd1498Szrj #define MAX_VECTORIZATION_FACTOR INT_MAX
100038fd1498Szrj 
100138fd1498Szrj /* Nonzero if TYPE represents a (scalar) boolean type or type
100238fd1498Szrj    in the middle-end compatible with it (unsigned precision 1 integral
100338fd1498Szrj    types).  Used to determine which types should be vectorized as
100438fd1498Szrj    VECTOR_BOOLEAN_TYPE_P.  */
100538fd1498Szrj 
100638fd1498Szrj #define VECT_SCALAR_BOOLEAN_TYPE_P(TYPE) \
100738fd1498Szrj   (TREE_CODE (TYPE) == BOOLEAN_TYPE		\
100838fd1498Szrj    || ((TREE_CODE (TYPE) == INTEGER_TYPE	\
100938fd1498Szrj 	|| TREE_CODE (TYPE) == ENUMERAL_TYPE)	\
101038fd1498Szrj        && TYPE_PRECISION (TYPE) == 1		\
101138fd1498Szrj        && TYPE_UNSIGNED (TYPE)))
101238fd1498Szrj 
101338fd1498Szrj extern vec<stmt_vec_info> stmt_vec_info_vec;
101438fd1498Szrj 
101538fd1498Szrj void init_stmt_vec_info_vec (void);
101638fd1498Szrj void free_stmt_vec_info_vec (void);
101738fd1498Szrj 
101838fd1498Szrj /* Return a stmt_vec_info corresponding to STMT.  */
101938fd1498Szrj 
102038fd1498Szrj static inline stmt_vec_info
vinfo_for_stmt(gimple * stmt)102138fd1498Szrj vinfo_for_stmt (gimple *stmt)
102238fd1498Szrj {
102338fd1498Szrj   int uid = gimple_uid (stmt);
102438fd1498Szrj   if (uid <= 0)
102538fd1498Szrj     return NULL;
102638fd1498Szrj 
102738fd1498Szrj   return stmt_vec_info_vec[uid - 1];
102838fd1498Szrj }
102938fd1498Szrj 
103038fd1498Szrj /* Set vectorizer information INFO for STMT.  */
103138fd1498Szrj 
103238fd1498Szrj static inline void
set_vinfo_for_stmt(gimple * stmt,stmt_vec_info info)103338fd1498Szrj set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info)
103438fd1498Szrj {
103538fd1498Szrj   unsigned int uid = gimple_uid (stmt);
103638fd1498Szrj   if (uid == 0)
103738fd1498Szrj     {
103838fd1498Szrj       gcc_checking_assert (info);
103938fd1498Szrj       uid = stmt_vec_info_vec.length () + 1;
104038fd1498Szrj       gimple_set_uid (stmt, uid);
104138fd1498Szrj       stmt_vec_info_vec.safe_push (info);
104238fd1498Szrj     }
104338fd1498Szrj   else
104438fd1498Szrj     {
104538fd1498Szrj       gcc_checking_assert (info == NULL);
104638fd1498Szrj       stmt_vec_info_vec[uid - 1] = info;
104738fd1498Szrj     }
104838fd1498Szrj }
104938fd1498Szrj 
105038fd1498Szrj /* Return TRUE if a statement represented by STMT_INFO is a part of a
105138fd1498Szrj    pattern.  */
105238fd1498Szrj 
105338fd1498Szrj static inline bool
is_pattern_stmt_p(stmt_vec_info stmt_info)105438fd1498Szrj is_pattern_stmt_p (stmt_vec_info stmt_info)
105538fd1498Szrj {
105638fd1498Szrj   gimple *related_stmt;
105738fd1498Szrj   stmt_vec_info related_stmt_info;
105838fd1498Szrj 
105938fd1498Szrj   related_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
106038fd1498Szrj   if (related_stmt
106138fd1498Szrj       && (related_stmt_info = vinfo_for_stmt (related_stmt))
106238fd1498Szrj       && STMT_VINFO_IN_PATTERN_P (related_stmt_info))
106338fd1498Szrj     return true;
106438fd1498Szrj 
106538fd1498Szrj   return false;
106638fd1498Szrj }
106738fd1498Szrj 
1068*58e805e6Szrj /* Return the later statement between STMT1 and STMT2.  */
1069*58e805e6Szrj 
1070*58e805e6Szrj static inline gimple *
get_later_stmt(gimple * stmt1,gimple * stmt2)1071*58e805e6Szrj get_later_stmt (gimple *stmt1, gimple *stmt2)
1072*58e805e6Szrj {
1073*58e805e6Szrj   unsigned int uid1, uid2;
1074*58e805e6Szrj 
1075*58e805e6Szrj   if (stmt1 == NULL)
1076*58e805e6Szrj     return stmt2;
1077*58e805e6Szrj 
1078*58e805e6Szrj   if (stmt2 == NULL)
1079*58e805e6Szrj     return stmt1;
1080*58e805e6Szrj 
1081*58e805e6Szrj   stmt_vec_info stmt_info1 = vinfo_for_stmt (stmt1);
1082*58e805e6Szrj   stmt_vec_info stmt_info2 = vinfo_for_stmt (stmt2);
1083*58e805e6Szrj   uid1 = gimple_uid (is_pattern_stmt_p (stmt_info1)
1084*58e805e6Szrj 		     ? STMT_VINFO_RELATED_STMT (stmt_info1) : stmt1);
1085*58e805e6Szrj   uid2 = gimple_uid (is_pattern_stmt_p (stmt_info2)
1086*58e805e6Szrj 		     ? STMT_VINFO_RELATED_STMT (stmt_info2) : stmt2);
1087*58e805e6Szrj 
1088*58e805e6Szrj   if (uid1 == 0 || uid2 == 0)
1089*58e805e6Szrj     return NULL;
1090*58e805e6Szrj 
1091*58e805e6Szrj   gcc_assert (uid1 <= stmt_vec_info_vec.length ());
1092*58e805e6Szrj   gcc_assert (uid2 <= stmt_vec_info_vec.length ());
1093*58e805e6Szrj 
1094*58e805e6Szrj   if (uid1 > uid2)
1095*58e805e6Szrj     return stmt1;
1096*58e805e6Szrj   else
1097*58e805e6Szrj     return stmt2;
1098*58e805e6Szrj }
1099*58e805e6Szrj 
110038fd1498Szrj /* Return true if BB is a loop header.  */
110138fd1498Szrj 
110238fd1498Szrj static inline bool
is_loop_header_bb_p(basic_block bb)110338fd1498Szrj is_loop_header_bb_p (basic_block bb)
110438fd1498Szrj {
110538fd1498Szrj   if (bb == (bb->loop_father)->header)
110638fd1498Szrj     return true;
110738fd1498Szrj   gcc_checking_assert (EDGE_COUNT (bb->preds) == 1);
110838fd1498Szrj   return false;
110938fd1498Szrj }
111038fd1498Szrj 
111138fd1498Szrj /* Return pow2 (X).  */
111238fd1498Szrj 
111338fd1498Szrj static inline int
vect_pow2(int x)111438fd1498Szrj vect_pow2 (int x)
111538fd1498Szrj {
111638fd1498Szrj   int i, res = 1;
111738fd1498Szrj 
111838fd1498Szrj   for (i = 0; i < x; i++)
111938fd1498Szrj     res *= 2;
112038fd1498Szrj 
112138fd1498Szrj   return res;
112238fd1498Szrj }
112338fd1498Szrj 
112438fd1498Szrj /* Alias targetm.vectorize.builtin_vectorization_cost.  */
112538fd1498Szrj 
112638fd1498Szrj static inline int
builtin_vectorization_cost(enum vect_cost_for_stmt type_of_cost,tree vectype,int misalign)112738fd1498Szrj builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
112838fd1498Szrj 			    tree vectype, int misalign)
112938fd1498Szrj {
113038fd1498Szrj   return targetm.vectorize.builtin_vectorization_cost (type_of_cost,
113138fd1498Szrj 						       vectype, misalign);
113238fd1498Szrj }
113338fd1498Szrj 
113438fd1498Szrj /* Get cost by calling cost target builtin.  */
113538fd1498Szrj 
113638fd1498Szrj static inline
vect_get_stmt_cost(enum vect_cost_for_stmt type_of_cost)113738fd1498Szrj int vect_get_stmt_cost (enum vect_cost_for_stmt type_of_cost)
113838fd1498Szrj {
113938fd1498Szrj   return builtin_vectorization_cost (type_of_cost, NULL, 0);
114038fd1498Szrj }
114138fd1498Szrj 
114238fd1498Szrj /* Alias targetm.vectorize.init_cost.  */
114338fd1498Szrj 
114438fd1498Szrj static inline void *
init_cost(struct loop * loop_info)114538fd1498Szrj init_cost (struct loop *loop_info)
114638fd1498Szrj {
114738fd1498Szrj   return targetm.vectorize.init_cost (loop_info);
114838fd1498Szrj }
114938fd1498Szrj 
115038fd1498Szrj /* Alias targetm.vectorize.add_stmt_cost.  */
115138fd1498Szrj 
115238fd1498Szrj static inline unsigned
add_stmt_cost(void * data,int count,enum vect_cost_for_stmt kind,stmt_vec_info stmt_info,int misalign,enum vect_cost_model_location where)115338fd1498Szrj add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
115438fd1498Szrj 	       stmt_vec_info stmt_info, int misalign,
115538fd1498Szrj 	       enum vect_cost_model_location where)
115638fd1498Szrj {
115738fd1498Szrj   return targetm.vectorize.add_stmt_cost (data, count, kind,
115838fd1498Szrj 					  stmt_info, misalign, where);
115938fd1498Szrj }
116038fd1498Szrj 
116138fd1498Szrj /* Alias targetm.vectorize.finish_cost.  */
116238fd1498Szrj 
116338fd1498Szrj static inline void
finish_cost(void * data,unsigned * prologue_cost,unsigned * body_cost,unsigned * epilogue_cost)116438fd1498Szrj finish_cost (void *data, unsigned *prologue_cost,
116538fd1498Szrj 	     unsigned *body_cost, unsigned *epilogue_cost)
116638fd1498Szrj {
116738fd1498Szrj   targetm.vectorize.finish_cost (data, prologue_cost, body_cost, epilogue_cost);
116838fd1498Szrj }
116938fd1498Szrj 
117038fd1498Szrj /* Alias targetm.vectorize.destroy_cost_data.  */
117138fd1498Szrj 
117238fd1498Szrj static inline void
destroy_cost_data(void * data)117338fd1498Szrj destroy_cost_data (void *data)
117438fd1498Szrj {
117538fd1498Szrj   targetm.vectorize.destroy_cost_data (data);
117638fd1498Szrj }
117738fd1498Szrj 
117838fd1498Szrj /*-----------------------------------------------------------------*/
117938fd1498Szrj /* Info on data references alignment.                              */
118038fd1498Szrj /*-----------------------------------------------------------------*/
118138fd1498Szrj inline void
set_dr_misalignment(struct data_reference * dr,int val)118238fd1498Szrj set_dr_misalignment (struct data_reference *dr, int val)
118338fd1498Szrj {
118438fd1498Szrj   dataref_aux *data_aux = DR_VECT_AUX (dr);
118538fd1498Szrj 
118638fd1498Szrj   if (!data_aux)
118738fd1498Szrj     {
118838fd1498Szrj       data_aux = XCNEW (dataref_aux);
118938fd1498Szrj       dr->aux = data_aux;
119038fd1498Szrj     }
119138fd1498Szrj 
119238fd1498Szrj   data_aux->misalignment = val;
119338fd1498Szrj }
119438fd1498Szrj 
119538fd1498Szrj inline int
dr_misalignment(struct data_reference * dr)119638fd1498Szrj dr_misalignment (struct data_reference *dr)
119738fd1498Szrj {
119838fd1498Szrj   return DR_VECT_AUX (dr)->misalignment;
119938fd1498Szrj }
120038fd1498Szrj 
120138fd1498Szrj /* Reflects actual alignment of first access in the vectorized loop,
120238fd1498Szrj    taking into account peeling/versioning if applied.  */
120338fd1498Szrj #define DR_MISALIGNMENT(DR) dr_misalignment (DR)
120438fd1498Szrj #define SET_DR_MISALIGNMENT(DR, VAL) set_dr_misalignment (DR, VAL)
120538fd1498Szrj #define DR_MISALIGNMENT_UNKNOWN (-1)
120638fd1498Szrj 
120738fd1498Szrj /* Only defined once DR_MISALIGNMENT is defined.  */
120838fd1498Szrj #define DR_TARGET_ALIGNMENT(DR) DR_VECT_AUX (DR)->target_alignment
120938fd1498Szrj 
121038fd1498Szrj /* Return true if data access DR is aligned to its target alignment
121138fd1498Szrj    (which may be less than a full vector).  */
121238fd1498Szrj 
121338fd1498Szrj static inline bool
aligned_access_p(struct data_reference * data_ref_info)121438fd1498Szrj aligned_access_p (struct data_reference *data_ref_info)
121538fd1498Szrj {
121638fd1498Szrj   return (DR_MISALIGNMENT (data_ref_info) == 0);
121738fd1498Szrj }
121838fd1498Szrj 
121938fd1498Szrj /* Return TRUE if the alignment of the data access is known, and FALSE
122038fd1498Szrj    otherwise.  */
122138fd1498Szrj 
122238fd1498Szrj static inline bool
known_alignment_for_access_p(struct data_reference * data_ref_info)122338fd1498Szrj known_alignment_for_access_p (struct data_reference *data_ref_info)
122438fd1498Szrj {
122538fd1498Szrj   return (DR_MISALIGNMENT (data_ref_info) != DR_MISALIGNMENT_UNKNOWN);
122638fd1498Szrj }
122738fd1498Szrj 
122838fd1498Szrj /* Return the minimum alignment in bytes that the vectorized version
122938fd1498Szrj    of DR is guaranteed to have.  */
123038fd1498Szrj 
123138fd1498Szrj static inline unsigned int
vect_known_alignment_in_bytes(struct data_reference * dr)123238fd1498Szrj vect_known_alignment_in_bytes (struct data_reference *dr)
123338fd1498Szrj {
123438fd1498Szrj   if (DR_MISALIGNMENT (dr) == DR_MISALIGNMENT_UNKNOWN)
123538fd1498Szrj     return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr)));
123638fd1498Szrj   if (DR_MISALIGNMENT (dr) == 0)
123738fd1498Szrj     return DR_TARGET_ALIGNMENT (dr);
123838fd1498Szrj   return DR_MISALIGNMENT (dr) & -DR_MISALIGNMENT (dr);
123938fd1498Szrj }
124038fd1498Szrj 
124138fd1498Szrj /* Return the behavior of DR with respect to the vectorization context
124238fd1498Szrj    (which for outer loop vectorization might not be the behavior recorded
124338fd1498Szrj    in DR itself).  */
124438fd1498Szrj 
124538fd1498Szrj static inline innermost_loop_behavior *
vect_dr_behavior(data_reference * dr)124638fd1498Szrj vect_dr_behavior (data_reference *dr)
124738fd1498Szrj {
124838fd1498Szrj   gimple *stmt = DR_STMT (dr);
124938fd1498Szrj   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
125038fd1498Szrj   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
125138fd1498Szrj   if (loop_vinfo == NULL
125238fd1498Szrj       || !nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt))
125338fd1498Szrj     return &DR_INNERMOST (dr);
125438fd1498Szrj   else
125538fd1498Szrj     return &STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info);
125638fd1498Szrj }
125738fd1498Szrj 
125838fd1498Szrj /* Return true if the vect cost model is unlimited.  */
125938fd1498Szrj static inline bool
unlimited_cost_model(loop_p loop)126038fd1498Szrj unlimited_cost_model (loop_p loop)
126138fd1498Szrj {
126238fd1498Szrj   if (loop != NULL && loop->force_vectorize
126338fd1498Szrj       && flag_simd_cost_model != VECT_COST_MODEL_DEFAULT)
126438fd1498Szrj     return flag_simd_cost_model == VECT_COST_MODEL_UNLIMITED;
126538fd1498Szrj   return (flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED);
126638fd1498Szrj }
126738fd1498Szrj 
126838fd1498Szrj /* Return true if the loop described by LOOP_VINFO is fully-masked and
126938fd1498Szrj    if the first iteration should use a partial mask in order to achieve
127038fd1498Szrj    alignment.  */
127138fd1498Szrj 
127238fd1498Szrj static inline bool
vect_use_loop_mask_for_alignment_p(loop_vec_info loop_vinfo)127338fd1498Szrj vect_use_loop_mask_for_alignment_p (loop_vec_info loop_vinfo)
127438fd1498Szrj {
127538fd1498Szrj   return (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
127638fd1498Szrj 	  && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo));
127738fd1498Szrj }
127838fd1498Szrj 
127938fd1498Szrj /* Return the number of vectors of type VECTYPE that are needed to get
128038fd1498Szrj    NUNITS elements.  NUNITS should be based on the vectorization factor,
128138fd1498Szrj    so it is always a known multiple of the number of elements in VECTYPE.  */
128238fd1498Szrj 
128338fd1498Szrj static inline unsigned int
vect_get_num_vectors(poly_uint64 nunits,tree vectype)128438fd1498Szrj vect_get_num_vectors (poly_uint64 nunits, tree vectype)
128538fd1498Szrj {
128638fd1498Szrj   return exact_div (nunits, TYPE_VECTOR_SUBPARTS (vectype)).to_constant ();
128738fd1498Szrj }
128838fd1498Szrj 
128938fd1498Szrj /* Return the number of copies needed for loop vectorization when
129038fd1498Szrj    a statement operates on vectors of type VECTYPE.  This is the
129138fd1498Szrj    vectorization factor divided by the number of elements in
129238fd1498Szrj    VECTYPE and is always known at compile time.  */
129338fd1498Szrj 
129438fd1498Szrj static inline unsigned int
vect_get_num_copies(loop_vec_info loop_vinfo,tree vectype)129538fd1498Szrj vect_get_num_copies (loop_vec_info loop_vinfo, tree vectype)
129638fd1498Szrj {
129738fd1498Szrj   return vect_get_num_vectors (LOOP_VINFO_VECT_FACTOR (loop_vinfo), vectype);
129838fd1498Szrj }
129938fd1498Szrj 
130038fd1498Szrj /* Update maximum unit count *MAX_NUNITS so that it accounts for
130138fd1498Szrj    the number of units in vector type VECTYPE.  *MAX_NUNITS can be 1
130238fd1498Szrj    if we haven't yet recorded any vector types.  */
130338fd1498Szrj 
130438fd1498Szrj static inline void
vect_update_max_nunits(poly_uint64 * max_nunits,tree vectype)130538fd1498Szrj vect_update_max_nunits (poly_uint64 *max_nunits, tree vectype)
130638fd1498Szrj {
130738fd1498Szrj   /* All unit counts have the form current_vector_size * X for some
130838fd1498Szrj      rational X, so two unit sizes must have a common multiple.
130938fd1498Szrj      Everything is a multiple of the initial value of 1.  */
131038fd1498Szrj   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
131138fd1498Szrj   *max_nunits = force_common_multiple (*max_nunits, nunits);
131238fd1498Szrj }
131338fd1498Szrj 
131438fd1498Szrj /* Return the vectorization factor that should be used for costing
131538fd1498Szrj    purposes while vectorizing the loop described by LOOP_VINFO.
131638fd1498Szrj    Pick a reasonable estimate if the vectorization factor isn't
131738fd1498Szrj    known at compile time.  */
131838fd1498Szrj 
131938fd1498Szrj static inline unsigned int
vect_vf_for_cost(loop_vec_info loop_vinfo)132038fd1498Szrj vect_vf_for_cost (loop_vec_info loop_vinfo)
132138fd1498Szrj {
132238fd1498Szrj   return estimated_poly_value (LOOP_VINFO_VECT_FACTOR (loop_vinfo));
132338fd1498Szrj }
132438fd1498Szrj 
132538fd1498Szrj /* Estimate the number of elements in VEC_TYPE for costing purposes.
132638fd1498Szrj    Pick a reasonable estimate if the exact number isn't known at
132738fd1498Szrj    compile time.  */
132838fd1498Szrj 
132938fd1498Szrj static inline unsigned int
vect_nunits_for_cost(tree vec_type)133038fd1498Szrj vect_nunits_for_cost (tree vec_type)
133138fd1498Szrj {
133238fd1498Szrj   return estimated_poly_value (TYPE_VECTOR_SUBPARTS (vec_type));
133338fd1498Szrj }
133438fd1498Szrj 
133538fd1498Szrj /* Return the maximum possible vectorization factor for LOOP_VINFO.  */
133638fd1498Szrj 
133738fd1498Szrj static inline unsigned HOST_WIDE_INT
vect_max_vf(loop_vec_info loop_vinfo)133838fd1498Szrj vect_max_vf (loop_vec_info loop_vinfo)
133938fd1498Szrj {
134038fd1498Szrj   unsigned HOST_WIDE_INT vf;
134138fd1498Szrj   if (LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&vf))
134238fd1498Szrj     return vf;
134338fd1498Szrj   return MAX_VECTORIZATION_FACTOR;
134438fd1498Szrj }
134538fd1498Szrj 
134638fd1498Szrj /* Return the size of the value accessed by unvectorized data reference DR.
134738fd1498Szrj    This is only valid once STMT_VINFO_VECTYPE has been calculated for the
134838fd1498Szrj    associated gimple statement, since that guarantees that DR accesses
134938fd1498Szrj    either a scalar or a scalar equivalent.  ("Scalar equivalent" here
135038fd1498Szrj    includes things like V1SI, which can be vectorized in the same way
135138fd1498Szrj    as a plain SI.)  */
135238fd1498Szrj 
135338fd1498Szrj inline unsigned int
vect_get_scalar_dr_size(struct data_reference * dr)135438fd1498Szrj vect_get_scalar_dr_size (struct data_reference *dr)
135538fd1498Szrj {
135638fd1498Szrj   return tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
135738fd1498Szrj }
135838fd1498Szrj 
135938fd1498Szrj /* Source location */
136038fd1498Szrj extern source_location vect_location;
136138fd1498Szrj 
136238fd1498Szrj /*-----------------------------------------------------------------*/
136338fd1498Szrj /* Function prototypes.                                            */
136438fd1498Szrj /*-----------------------------------------------------------------*/
136538fd1498Szrj 
136638fd1498Szrj /* Simple loop peeling and versioning utilities for vectorizer's purposes -
136738fd1498Szrj    in tree-vect-loop-manip.c.  */
136838fd1498Szrj extern void vect_set_loop_condition (struct loop *, loop_vec_info,
136938fd1498Szrj 				     tree, tree, tree, bool);
137038fd1498Szrj extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
137138fd1498Szrj struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *,
137238fd1498Szrj 						     struct loop *, edge);
137338fd1498Szrj extern void vect_loop_versioning (loop_vec_info, unsigned int, bool,
137438fd1498Szrj 				  poly_uint64);
137538fd1498Szrj extern struct loop *vect_do_peeling (loop_vec_info, tree, tree,
137638fd1498Szrj 				     tree *, tree *, tree *, int, bool, bool);
137738fd1498Szrj extern void vect_prepare_for_masked_peels (loop_vec_info);
137838fd1498Szrj extern source_location find_loop_location (struct loop *);
137938fd1498Szrj extern bool vect_can_advance_ivs_p (loop_vec_info);
138038fd1498Szrj 
138138fd1498Szrj /* In tree-vect-stmts.c.  */
138238fd1498Szrj extern poly_uint64 current_vector_size;
138338fd1498Szrj extern tree get_vectype_for_scalar_type (tree);
138438fd1498Szrj extern tree get_vectype_for_scalar_type_and_size (tree, poly_uint64);
138538fd1498Szrj extern tree get_mask_type_for_scalar_type (tree);
138638fd1498Szrj extern tree get_same_sized_vectype (tree, tree);
138738fd1498Szrj extern bool vect_get_loop_mask_type (loop_vec_info);
138838fd1498Szrj extern bool vect_is_simple_use (tree, vec_info *, gimple **,
138938fd1498Szrj                                 enum vect_def_type *);
139038fd1498Szrj extern bool vect_is_simple_use (tree, vec_info *, gimple **,
139138fd1498Szrj 				enum vect_def_type *, tree *);
139238fd1498Szrj extern bool supportable_widening_operation (enum tree_code, gimple *, tree,
139338fd1498Szrj 					    tree, enum tree_code *,
139438fd1498Szrj 					    enum tree_code *, int *,
139538fd1498Szrj 					    vec<tree> *);
139638fd1498Szrj extern bool supportable_narrowing_operation (enum tree_code, tree, tree,
139738fd1498Szrj 					     enum tree_code *,
139838fd1498Szrj 					     int *, vec<tree> *);
139938fd1498Szrj extern stmt_vec_info new_stmt_vec_info (gimple *stmt, vec_info *);
140038fd1498Szrj extern void free_stmt_vec_info (gimple *stmt);
140138fd1498Szrj extern void vect_model_simple_cost (stmt_vec_info, int, enum vect_def_type *,
140238fd1498Szrj 				    int, stmt_vector_for_cost *,
140338fd1498Szrj 				    stmt_vector_for_cost *);
140438fd1498Szrj extern void vect_model_store_cost (stmt_vec_info, int, vect_memory_access_type,
140538fd1498Szrj 				   vec_load_store_type, slp_tree,
140638fd1498Szrj 				   stmt_vector_for_cost *,
140738fd1498Szrj 				   stmt_vector_for_cost *);
140838fd1498Szrj extern void vect_model_load_cost (stmt_vec_info, int, vect_memory_access_type,
140938fd1498Szrj 				  slp_tree, stmt_vector_for_cost *,
141038fd1498Szrj 				  stmt_vector_for_cost *);
141138fd1498Szrj extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
141238fd1498Szrj 				  enum vect_cost_for_stmt, stmt_vec_info,
141338fd1498Szrj 				  int, enum vect_cost_model_location);
141438fd1498Szrj extern void vect_finish_replace_stmt (gimple *, gimple *);
141538fd1498Szrj extern void vect_finish_stmt_generation (gimple *, gimple *,
141638fd1498Szrj                                          gimple_stmt_iterator *);
141738fd1498Szrj extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
141838fd1498Szrj extern tree vect_get_store_rhs (gimple *);
141938fd1498Szrj extern tree vect_get_vec_def_for_operand_1 (gimple *, enum vect_def_type);
142038fd1498Szrj extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL);
142138fd1498Szrj extern void vect_get_vec_defs (tree, tree, gimple *, vec<tree> *,
142238fd1498Szrj 			       vec<tree> *, slp_tree);
142338fd1498Szrj extern void vect_get_vec_defs_for_stmt_copy (enum vect_def_type *,
142438fd1498Szrj 					     vec<tree> *, vec<tree> *);
142538fd1498Szrj extern tree vect_init_vector (gimple *, tree, tree,
142638fd1498Szrj                               gimple_stmt_iterator *);
142738fd1498Szrj extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);
142838fd1498Szrj extern bool vect_transform_stmt (gimple *, gimple_stmt_iterator *,
142938fd1498Szrj                                  bool *, slp_tree, slp_instance);
143038fd1498Szrj extern void vect_remove_stores (gimple *);
143138fd1498Szrj extern bool vect_analyze_stmt (gimple *, bool *, slp_tree, slp_instance);
143238fd1498Szrj extern bool vectorizable_condition (gimple *, gimple_stmt_iterator *,
143338fd1498Szrj 				    gimple **, tree, int, slp_tree);
143438fd1498Szrj extern void vect_get_load_cost (struct data_reference *, int, bool,
143538fd1498Szrj 				unsigned int *, unsigned int *,
143638fd1498Szrj 				stmt_vector_for_cost *,
143738fd1498Szrj 				stmt_vector_for_cost *, bool);
143838fd1498Szrj extern void vect_get_store_cost (struct data_reference *, int,
143938fd1498Szrj 				 unsigned int *, stmt_vector_for_cost *);
144038fd1498Szrj extern bool vect_supportable_shift (enum tree_code, tree);
144138fd1498Szrj extern tree vect_gen_perm_mask_any (tree, const vec_perm_indices &);
144238fd1498Szrj extern tree vect_gen_perm_mask_checked (tree, const vec_perm_indices &);
144338fd1498Szrj extern void optimize_mask_stores (struct loop*);
144438fd1498Szrj extern gcall *vect_gen_while (tree, tree, tree);
144538fd1498Szrj extern tree vect_gen_while_not (gimple_seq *, tree, tree, tree);
144638fd1498Szrj 
144738fd1498Szrj /* In tree-vect-data-refs.c.  */
144838fd1498Szrj extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int);
144938fd1498Szrj extern enum dr_alignment_support vect_supportable_dr_alignment
145038fd1498Szrj                                            (struct data_reference *, bool);
145138fd1498Szrj extern tree vect_get_smallest_scalar_type (gimple *, HOST_WIDE_INT *,
145238fd1498Szrj                                            HOST_WIDE_INT *);
145338fd1498Szrj extern bool vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *);
145438fd1498Szrj extern bool vect_slp_analyze_instance_dependence (slp_instance);
145538fd1498Szrj extern bool vect_enhance_data_refs_alignment (loop_vec_info);
145638fd1498Szrj extern bool vect_analyze_data_refs_alignment (loop_vec_info);
145738fd1498Szrj extern bool vect_verify_datarefs_alignment (loop_vec_info);
145838fd1498Szrj extern bool vect_slp_analyze_and_verify_instance_alignment (slp_instance);
145938fd1498Szrj extern bool vect_analyze_data_ref_accesses (vec_info *);
146038fd1498Szrj extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
146138fd1498Szrj extern bool vect_gather_scatter_fn_p (bool, bool, tree, tree, unsigned int,
146238fd1498Szrj 				      signop, int, internal_fn *, tree *);
146338fd1498Szrj extern bool vect_check_gather_scatter (gimple *, loop_vec_info,
146438fd1498Szrj 				       gather_scatter_info *);
146538fd1498Szrj extern bool vect_analyze_data_refs (vec_info *, poly_uint64 *);
146638fd1498Szrj extern void vect_record_base_alignments (vec_info *);
146738fd1498Szrj extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
146838fd1498Szrj 				      tree *, gimple_stmt_iterator *,
146938fd1498Szrj 				      gimple **, bool, bool *,
147038fd1498Szrj 				      tree = NULL_TREE, tree = NULL_TREE);
147138fd1498Szrj extern tree bump_vector_ptr (tree, gimple *, gimple_stmt_iterator *, gimple *,
147238fd1498Szrj 			     tree);
147338fd1498Szrj extern void vect_copy_ref_info (tree, tree);
147438fd1498Szrj extern tree vect_create_destination_var (tree, tree);
147538fd1498Szrj extern bool vect_grouped_store_supported (tree, unsigned HOST_WIDE_INT);
147638fd1498Szrj extern bool vect_store_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
147738fd1498Szrj extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
147838fd1498Szrj extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
147938fd1498Szrj extern void vect_permute_store_chain (vec<tree> ,unsigned int, gimple *,
148038fd1498Szrj                                     gimple_stmt_iterator *, vec<tree> *);
148138fd1498Szrj extern tree vect_setup_realignment (gimple *, gimple_stmt_iterator *, tree *,
148238fd1498Szrj                                     enum dr_alignment_support, tree,
148338fd1498Szrj                                     struct loop **);
148438fd1498Szrj extern void vect_transform_grouped_load (gimple *, vec<tree> , int,
148538fd1498Szrj                                          gimple_stmt_iterator *);
148638fd1498Szrj extern void vect_record_grouped_load_vectors (gimple *, vec<tree> );
148738fd1498Szrj extern tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
148838fd1498Szrj extern tree vect_get_new_ssa_name (tree, enum vect_var_kind,
148938fd1498Szrj 				   const char * = NULL);
149038fd1498Szrj extern tree vect_create_addr_base_for_vector_ref (gimple *, gimple_seq *,
149138fd1498Szrj 						  tree, tree = NULL_TREE);
149238fd1498Szrj 
149338fd1498Szrj /* In tree-vect-loop.c.  */
149438fd1498Szrj /* FORNOW: Used in tree-parloops.c.  */
149538fd1498Szrj extern gimple *vect_force_simple_reduction (loop_vec_info, gimple *,
149638fd1498Szrj 					    bool *, bool);
149738fd1498Szrj /* Used in gimple-loop-interchange.c.  */
149838fd1498Szrj extern bool check_reduction_path (location_t, loop_p, gphi *, tree,
149938fd1498Szrj 				  enum tree_code);
150038fd1498Szrj /* Drive for loop analysis stage.  */
150138fd1498Szrj extern loop_vec_info vect_analyze_loop (struct loop *, loop_vec_info);
150238fd1498Szrj extern tree vect_build_loop_niters (loop_vec_info, bool * = NULL);
150338fd1498Szrj extern void vect_gen_vector_loop_niters (loop_vec_info, tree, tree *,
150438fd1498Szrj 					 tree *, bool);
150538fd1498Szrj extern tree vect_halve_mask_nunits (tree);
150638fd1498Szrj extern tree vect_double_mask_nunits (tree);
150738fd1498Szrj extern void vect_record_loop_mask (loop_vec_info, vec_loop_masks *,
150838fd1498Szrj 				   unsigned int, tree);
150938fd1498Szrj extern tree vect_get_loop_mask (gimple_stmt_iterator *, vec_loop_masks *,
151038fd1498Szrj 				unsigned int, tree, unsigned int);
151138fd1498Szrj 
151238fd1498Szrj /* Drive for loop transformation stage.  */
151338fd1498Szrj extern struct loop *vect_transform_loop (loop_vec_info);
151438fd1498Szrj extern loop_vec_info vect_analyze_loop_form (struct loop *);
151538fd1498Szrj extern bool vectorizable_live_operation (gimple *, gimple_stmt_iterator *,
151638fd1498Szrj 					 slp_tree, int, gimple **);
151738fd1498Szrj extern bool vectorizable_reduction (gimple *, gimple_stmt_iterator *,
151838fd1498Szrj 				    gimple **, slp_tree, slp_instance);
151938fd1498Szrj extern bool vectorizable_induction (gimple *, gimple_stmt_iterator *,
152038fd1498Szrj 				    gimple **, slp_tree);
152138fd1498Szrj extern tree get_initial_def_for_reduction (gimple *, tree, tree *);
152238fd1498Szrj extern bool vect_worthwhile_without_simd_p (vec_info *, tree_code);
152338fd1498Szrj extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
152438fd1498Szrj 					stmt_vector_for_cost *,
152538fd1498Szrj 					stmt_vector_for_cost *,
152638fd1498Szrj 					stmt_vector_for_cost *);
152738fd1498Szrj extern tree cse_and_gimplify_to_preheader (loop_vec_info, tree);
152838fd1498Szrj 
152938fd1498Szrj /* In tree-vect-slp.c.  */
153038fd1498Szrj extern void vect_free_slp_instance (slp_instance);
153138fd1498Szrj extern bool vect_transform_slp_perm_load (slp_tree, vec<tree> ,
153238fd1498Szrj 					  gimple_stmt_iterator *, poly_uint64,
153338fd1498Szrj 					  slp_instance, bool, unsigned *);
153438fd1498Szrj extern bool vect_slp_analyze_operations (vec_info *);
153538fd1498Szrj extern bool vect_schedule_slp (vec_info *);
153638fd1498Szrj extern bool vect_analyze_slp (vec_info *, unsigned);
153738fd1498Szrj extern bool vect_make_slp_decision (loop_vec_info);
153838fd1498Szrj extern void vect_detect_hybrid_slp (loop_vec_info);
153938fd1498Szrj extern void vect_get_slp_defs (vec<tree> , slp_tree, vec<vec<tree> > *);
154038fd1498Szrj extern bool vect_slp_bb (basic_block);
154138fd1498Szrj extern gimple *vect_find_last_scalar_stmt_in_slp (slp_tree);
154238fd1498Szrj extern bool is_simple_and_all_uses_invariant (gimple *, loop_vec_info);
154338fd1498Szrj extern bool can_duplicate_and_interleave_p (unsigned int, machine_mode,
154438fd1498Szrj 					    unsigned int * = NULL,
154538fd1498Szrj 					    tree * = NULL, tree * = NULL);
154638fd1498Szrj extern void duplicate_and_interleave (gimple_seq *, tree, vec<tree>,
154738fd1498Szrj 				      unsigned int, vec<tree> &);
154838fd1498Szrj extern int vect_get_place_in_interleaving_chain (gimple *, gimple *);
154938fd1498Szrj 
155038fd1498Szrj /* In tree-vect-patterns.c.  */
155138fd1498Szrj /* Pattern recognition functions.
155238fd1498Szrj    Additional pattern recognition functions can (and will) be added
155338fd1498Szrj    in the future.  */
155438fd1498Szrj typedef gimple *(* vect_recog_func_ptr) (vec<gimple *> *, tree *, tree *);
155538fd1498Szrj #define NUM_PATTERNS 15
155638fd1498Szrj void vect_pattern_recog (vec_info *);
155738fd1498Szrj 
155838fd1498Szrj /* In tree-vectorizer.c.  */
155938fd1498Szrj unsigned vectorize_loops (void);
156038fd1498Szrj bool vect_stmt_in_region_p (vec_info *, gimple *);
156138fd1498Szrj void vect_free_loop_info_assumptions (struct loop *);
156238fd1498Szrj 
156338fd1498Szrj #endif  /* GCC_TREE_VECTORIZER_H  */
1564