summaryrefslogtreecommitdiff
path: root/gcc/tree-vectorizer.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vectorizer.h')
-rw-r--r--gcc/tree-vectorizer.h183
1 files changed, 143 insertions, 40 deletions
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index bd1d55a7fb..12bb904abe 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1,5 +1,5 @@
/* Vectorizer
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2017 Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
This file is part of GCC.
@@ -65,7 +65,8 @@ enum vect_def_type {
enum vect_reduction_type {
TREE_CODE_REDUCTION,
COND_REDUCTION,
- INTEGER_INDUC_COND_REDUCTION
+ INTEGER_INDUC_COND_REDUCTION,
+ CONST_COND_REDUCTION
};
#define VECTORIZABLE_CYCLE_DEF(D) (((D) == vect_reduction_def) \
@@ -146,19 +147,15 @@ typedef struct _slp_instance {
/* This struct is used to store the information of a data reference,
- including the data ref itself, the access offset (calculated by summing its
- offset and init) and the segment length for aliasing checks.
- This is used to merge alias checks. */
+ including the data ref itself and the segment length for aliasing
+ checks. This is used to merge alias checks. */
struct dr_with_seg_len
{
dr_with_seg_len (data_reference_p d, tree len)
- : dr (d),
- offset (size_binop (PLUS_EXPR, DR_OFFSET (d), DR_INIT (d))),
- seg_len (len) {}
+ : dr (d), seg_len (len) {}
data_reference_p dr;
- tree offset;
tree seg_len;
};
@@ -235,15 +232,14 @@ typedef struct _loop_vec_info : public vec_info {
tree num_iters;
/* Number of iterations of the original loop. */
tree num_iters_unchanged;
+ /* Condition under which this loop is analyzed and versioned. */
+ tree num_iters_assumptions;
/* Threshold of number of iterations below which vectorzation will not be
performed. It is calculated from MIN_PROFITABLE_ITERS and
PARAM_MIN_VECT_LOOP_BOUND. */
unsigned int th;
- /* Is the loop vectorizable? */
- bool vectorizable;
-
/* Unrolling factor */
int vectorization_factor;
@@ -278,10 +274,6 @@ typedef struct _loop_vec_info : public vec_info {
runtime (loop versioning) misalignment check. */
vec<gimple *> may_misalign_stmts;
- /* The unrolling factor needed to SLP the loop. In case of that pure SLP is
- applied to the loop, i.e., no unrolling is needed, this is 1. */
- unsigned slp_unrolling_factor;
-
/* Reduction cycles detected in the loop. Used in loop-aware SLP. */
vec<gimple *> reductions;
@@ -292,9 +284,16 @@ typedef struct _loop_vec_info : public vec_info {
/* Cost vector for a single scalar iteration. */
vec<stmt_info_for_cost> scalar_cost_vec;
+ /* The unrolling factor needed to SLP the loop. In case of that pure SLP is
+ applied to the loop, i.e., no unrolling is needed, this is 1. */
+ unsigned slp_unrolling_factor;
+
/* Cost of a single scalar iteration. */
int single_scalar_iteration_cost;
+ /* Is the loop vectorizable? */
+ bool vectorizable;
+
/* When we have grouped data accesses with gaps, we may introduce invalid
memory accesses. We peel the last iteration of the loop to prevent
this. */
@@ -329,12 +328,16 @@ typedef struct _loop_vec_info : public vec_info {
vectorize this, so this field would be false. */
bool no_data_dependencies;
+ /* Mark loops having masked stores. */
+ bool has_mask_store;
+
/* If if-conversion versioned this loop before conversion, this is the
loop version without if-conversion. */
struct loop *scalar_loop;
- /* Mark loops having masked stores. */
- bool has_mask_store;
+ /* For loops being epilogues of already vectorized loops
+ this points to the original vectorized loop. Otherwise NULL. */
+ _loop_vec_info *orig_loop_info;
} *loop_vec_info;
@@ -347,6 +350,7 @@ typedef struct _loop_vec_info : public vec_info {
prologue peeling retain total unchanged scalar loop iterations for
cost model. */
#define LOOP_VINFO_NITERS_UNCHANGED(L) (L)->num_iters_unchanged
+#define LOOP_VINFO_NITERS_ASSUMPTIONS(L) (L)->num_iters_assumptions
#define LOOP_VINFO_COST_MODEL_THRESHOLD(L) (L)->th
#define LOOP_VINFO_VECTORIZABLE_P(L) (L)->vectorizable
#define LOOP_VINFO_VECT_FACTOR(L) (L)->vectorization_factor
@@ -374,15 +378,28 @@ typedef struct _loop_vec_info : public vec_info {
#define LOOP_VINFO_HAS_MASK_STORE(L) (L)->has_mask_store
#define LOOP_VINFO_SCALAR_ITERATION_COST(L) (L)->scalar_cost_vec
#define LOOP_VINFO_SINGLE_SCALAR_ITERATION_COST(L) (L)->single_scalar_iteration_cost
+#define LOOP_VINFO_ORIG_LOOP_INFO(L) (L)->orig_loop_info
-#define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L) \
+#define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L) \
((L)->may_misalign_stmts.length () > 0)
-#define LOOP_REQUIRES_VERSIONING_FOR_ALIAS(L) \
+#define LOOP_REQUIRES_VERSIONING_FOR_ALIAS(L) \
((L)->may_alias_ddrs.length () > 0)
+#define LOOP_REQUIRES_VERSIONING_FOR_NITERS(L) \
+ (LOOP_VINFO_NITERS_ASSUMPTIONS (L))
+#define LOOP_REQUIRES_VERSIONING(L) \
+ (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (L) \
+ || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (L) \
+ || LOOP_REQUIRES_VERSIONING_FOR_NITERS (L))
#define LOOP_VINFO_NITERS_KNOWN_P(L) \
(tree_fits_shwi_p ((L)->num_iters) && tree_to_shwi ((L)->num_iters) > 0)
+#define LOOP_VINFO_EPILOGUE_P(L) \
+ (LOOP_VINFO_ORIG_LOOP_INFO (L) != NULL)
+
+#define LOOP_VINFO_ORIG_VECT_FACTOR(L) \
+ (LOOP_VINFO_VECT_FACTOR (LOOP_VINFO_ORIG_LOOP_INFO (L)))
+
static inline loop_vec_info
loop_vec_info_for_loop (struct loop *loop)
{
@@ -442,6 +459,9 @@ enum stmt_vec_info_type {
block. */
enum vect_relevant {
vect_unused_in_scope = 0,
+
+ /* The def is only used outside the loop. */
+ vect_used_only_live,
/* The def is in the inner loop, and the use is in the outer loop, and the
use is a reduction stmt. */
vect_used_in_outer_by_reduction,
@@ -482,6 +502,45 @@ enum slp_vect_type {
hybrid
};
+/* Describes how we're going to vectorize an individual load or store,
+ or a group of loads or stores. */
+enum vect_memory_access_type {
+ /* An access to an invariant address. This is used only for loads. */
+ VMAT_INVARIANT,
+
+ /* A simple contiguous access. */
+ VMAT_CONTIGUOUS,
+
+ /* A contiguous access that goes down in memory rather than up,
+ with no additional permutation. This is used only for stores
+ of invariants. */
+ VMAT_CONTIGUOUS_DOWN,
+
+ /* A simple contiguous access in which the elements need to be permuted
+ after loading or before storing. Only used for loop vectorization;
+ SLP uses separate permutes. */
+ VMAT_CONTIGUOUS_PERMUTE,
+
+ /* A simple contiguous access in which the elements need to be reversed
+ after loading or before storing. */
+ VMAT_CONTIGUOUS_REVERSE,
+
+ /* An access that uses IFN_LOAD_LANES or IFN_STORE_LANES. */
+ VMAT_LOAD_STORE_LANES,
+
+ /* An access in which each scalar element is loaded or stored
+ individually. */
+ VMAT_ELEMENTWISE,
+
+ /* A hybrid of VMAT_CONTIGUOUS and VMAT_ELEMENTWISE, used for grouped
+ SLP accesses. Each unrolled iteration uses a contiguous load
+ or store for the whole group, but the groups from separate iterations
+ are combined in the same way as for VMAT_ELEMENTWISE. */
+ VMAT_STRIDED_SLP,
+
+ /* The access uses gather loads or scatter stores. */
+ VMAT_GATHER_SCATTER
+};
typedef struct data_reference *dr_p;
@@ -496,6 +555,10 @@ typedef struct _stmt_vec_info {
/* Stmt is part of some pattern (computation idiom) */
bool in_pattern_p;
+ /* Is this statement vectorizable or should it be skipped in (partial)
+ vectorization. */
+ bool vectorizable;
+
/* The stmt to which this info struct refers to. */
gimple *stmt;
@@ -589,10 +652,6 @@ typedef struct _stmt_vec_info {
indicates whether the stmt needs to be vectorized. */
enum vect_relevant relevant;
- /* Is this statement vectorizable or should it be skipped in (partial)
- vectorization. */
- bool vectorizable;
-
/* For loads if this is a gather, for stores if this is a scatter. */
bool gather_scatter_p;
@@ -602,13 +661,42 @@ typedef struct _stmt_vec_info {
/* For both loads and stores. */
bool simd_lane_access_p;
+ /* Classifies how the load or store is going to be implemented
+ for loop vectorization. */
+ vect_memory_access_type memory_access_type;
+
/* For reduction loops, this is the type of reduction. */
enum vect_reduction_type v_reduc_type;
+ /* For CONST_COND_REDUCTION, record the reduc code. */
+ enum tree_code const_cond_reduc_code;
+
/* The number of scalar stmt references from active SLP instances. */
unsigned int num_slp_uses;
} *stmt_vec_info;
+/* Information about a gather/scatter call. */
+struct gather_scatter_info {
+ /* The FUNCTION_DECL for the built-in gather/scatter function. */
+ tree decl;
+
+ /* The loop-invariant base value. */
+ tree base;
+
+ /* The original scalar offset, which is a non-loop-invariant SSA_NAME. */
+ tree offset;
+
+ /* Each offset element should be multiplied by this amount before
+ being added to the base. */
+ int scale;
+
+ /* The definition type for the vectorized offset. */
+ enum vect_def_type offset_dt;
+
+ /* The type of the vectorized offset. */
+ tree offset_vectype;
+};
+
/* Access Functions. */
#define STMT_VINFO_TYPE(S) (S)->type
#define STMT_VINFO_STMT(S) (S)->stmt
@@ -634,8 +722,10 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
#define STMT_VINFO_GATHER_SCATTER_P(S) (S)->gather_scatter_p
#define STMT_VINFO_STRIDED_P(S) (S)->strided_p
+#define STMT_VINFO_MEMORY_ACCESS_TYPE(S) (S)->memory_access_type
#define STMT_VINFO_SIMD_LANE_ACCESS_P(S) (S)->simd_lane_access_p
#define STMT_VINFO_VEC_REDUCTION_TYPE(S) (S)->v_reduc_type
+#define STMT_VINFO_VEC_CONST_COND_REDUC_CODE(S) (S)->const_cond_reduc_code
#define STMT_VINFO_DR_BASE_ADDRESS(S) (S)->dr_base_address
#define STMT_VINFO_DR_INIT(S) (S)->dr_init
@@ -694,6 +784,18 @@ struct dataref_aux {
/* The maximum vectorization factor supported by any target (V64QI). */
#define MAX_VECTORIZATION_FACTOR 64
+/* Nonzero if TYPE represents a (scalar) boolean type or type
+ in the middle-end compatible with it (unsigned precision 1 integral
+ types). Used to determine which types should be vectorized as
+ VECTOR_BOOLEAN_TYPE_P. */
+
+#define VECT_SCALAR_BOOLEAN_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == BOOLEAN_TYPE \
+ || ((TREE_CODE (TYPE) == INTEGER_TYPE \
+ || TREE_CODE (TYPE) == ENUMERAL_TYPE) \
+ && TYPE_PRECISION (TYPE) == 1 \
+ && TYPE_UNSIGNED (TYPE)))
+
extern vec<stmt_vec_info> stmt_vec_info_vec;
void init_stmt_vec_info_vec (void);
@@ -953,10 +1055,8 @@ extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *,
struct loop *, edge);
extern void vect_loop_versioning (loop_vec_info, unsigned int, bool);
-extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree, tree,
- unsigned int, bool);
-extern void vect_do_peeling_for_alignment (loop_vec_info, tree,
- unsigned int, bool);
+extern struct loop *vect_do_peeling (loop_vec_info, tree, tree,
+ tree *, int, bool, bool);
extern source_location find_loop_location (struct loop *);
extern bool vect_can_advance_ivs_p (loop_vec_info);
@@ -981,12 +1081,12 @@ extern void free_stmt_vec_info (gimple *stmt);
extern void vect_model_simple_cost (stmt_vec_info, int, enum vect_def_type *,
stmt_vector_for_cost *,
stmt_vector_for_cost *);
-extern void vect_model_store_cost (stmt_vec_info, int, bool,
+extern void vect_model_store_cost (stmt_vec_info, int, vect_memory_access_type,
enum vect_def_type, slp_tree,
stmt_vector_for_cost *,
stmt_vector_for_cost *);
-extern void vect_model_load_cost (stmt_vec_info, int, bool, slp_tree,
- stmt_vector_for_cost *,
+extern void vect_model_load_cost (stmt_vec_info, int, vect_memory_access_type,
+ slp_tree, stmt_vector_for_cost *,
stmt_vector_for_cost *);
extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
enum vect_cost_for_stmt, stmt_vec_info,
@@ -994,6 +1094,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
extern void vect_finish_stmt_generation (gimple *, gimple *,
gimple_stmt_iterator *);
extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
+extern tree vect_get_vec_def_for_operand_1 (gimple *, enum vect_def_type);
extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL);
extern tree vect_init_vector (gimple *, tree, tree,
gimple_stmt_iterator *);
@@ -1004,8 +1105,6 @@ extern void vect_remove_stores (gimple *);
extern bool vect_analyze_stmt (gimple *, bool *, slp_tree);
extern bool vectorizable_condition (gimple *, gimple_stmt_iterator *,
gimple **, tree, int, slp_tree);
-extern bool vectorizable_comparison (gimple *, gimple_stmt_iterator *,
- gimple **, tree, int, slp_tree);
extern void vect_get_load_cost (struct data_reference *, int, bool,
unsigned int *, unsigned int *,
stmt_vector_for_cost *,
@@ -1033,8 +1132,8 @@ extern bool vect_verify_datarefs_alignment (loop_vec_info);
extern bool vect_slp_analyze_and_verify_instance_alignment (slp_instance);
extern bool vect_analyze_data_ref_accesses (vec_info *);
extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
-extern tree vect_check_gather_scatter (gimple *, loop_vec_info, tree *, tree *,
- int *);
+extern bool vect_check_gather_scatter (gimple *, loop_vec_info,
+ gather_scatter_info *);
extern bool vect_analyze_data_refs (vec_info *, int *);
extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
tree *, gimple_stmt_iterator *,
@@ -1045,7 +1144,7 @@ extern tree bump_vector_ptr (tree, gimple *, gimple_stmt_iterator *, gimple *,
extern tree vect_create_destination_var (tree, tree);
extern bool vect_grouped_store_supported (tree, unsigned HOST_WIDE_INT);
extern bool vect_store_lanes_supported (tree, unsigned HOST_WIDE_INT);
-extern bool vect_grouped_load_supported (tree, unsigned HOST_WIDE_INT);
+extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT);
extern void vect_permute_store_chain (vec<tree> ,unsigned int, gimple *,
gimple_stmt_iterator *, vec<tree> *);
@@ -1068,12 +1167,14 @@ extern void destroy_loop_vec_info (loop_vec_info, bool);
extern gimple *vect_force_simple_reduction (loop_vec_info, gimple *, bool,
bool *, bool);
/* Drive for loop analysis stage. */
-extern loop_vec_info vect_analyze_loop (struct loop *);
+extern loop_vec_info vect_analyze_loop (struct loop *, loop_vec_info);
+extern tree vect_build_loop_niters (loop_vec_info);
+extern void vect_gen_vector_loop_niters (loop_vec_info, tree, tree *, bool);
/* Drive for loop transformation stage. */
-extern void vect_transform_loop (loop_vec_info);
+extern struct loop *vect_transform_loop (loop_vec_info);
extern loop_vec_info vect_analyze_loop_form (struct loop *);
extern bool vectorizable_live_operation (gimple *, gimple_stmt_iterator *,
- gimple **);
+ slp_tree, int, gimple **);
extern bool vectorizable_reduction (gimple *, gimple_stmt_iterator *,
gimple **, slp_tree);
extern bool vectorizable_induction (gimple *, gimple_stmt_iterator *, gimple **);
@@ -1088,7 +1189,7 @@ extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
extern void vect_free_slp_instance (slp_instance);
extern bool vect_transform_slp_perm_load (slp_tree, vec<tree> ,
gimple_stmt_iterator *, int,
- slp_instance, bool);
+ slp_instance, bool, unsigned *);
extern bool vect_slp_analyze_operations (vec<slp_instance> slp_instances,
void *);
extern bool vect_schedule_slp (vec_info *);
@@ -1099,6 +1200,7 @@ extern void vect_get_slp_defs (vec<tree> , slp_tree,
vec<vec<tree> > *, int);
extern bool vect_slp_bb (basic_block);
extern gimple *vect_find_last_scalar_stmt_in_slp (slp_tree);
+extern bool is_simple_and_all_uses_invariant (gimple *, loop_vec_info);
/* In tree-vect-patterns.c. */
/* Pattern recognition functions.
@@ -1112,5 +1214,6 @@ void vect_pattern_recog (vec_info *);
unsigned vectorize_loops (void);
void vect_destroy_datarefs (vec_info *);
bool vect_stmt_in_region_p (vec_info *, gimple *);
+void vect_free_loop_info_assumptions (struct loop *);
#endif /* GCC_TREE_VECTORIZER_H */