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