This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[11/11] Insert pattern statements into vec_basic_blocks
- From: Richard Sandiford <richard dot sandiford at arm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 30 Jul 2018 12:47:26 +0100
- Subject: [11/11] Insert pattern statements into vec_basic_blocks
- References: <874lghez1a.fsf@arm.com>
The point of this patch is to put pattern statements in the same
vec_basic_block as the statements they replace, with the pattern
statements for S coming between S and S's original predecessor.
This removes the need to handle them specially in various places.
2018-07-30 Richard Sandiford <richard.sandiford@arm.com>
gcc/
* tree-vectorizer.h (vec_basic_block): Expand comment.
(_stmt_vec_info::pattern_def_seq): Delete.
(STMT_VINFO_PATTERN_DEF_SEQ): Likewise.
(is_main_pattern_stmt_p): New function.
* tree-vect-loop.c (vect_determine_vf_for_stmt_1): Rename to...
(vect_determine_vf_for_stmt): ...this, deleting the original
function with this name. Remove vectype_maybe_set_p argument
and test is_pattern_stmt_p instead. Retain the "examining..."
message from the previous vect_determine_vf_for_stmt.
(vect_compute_single_scalar_iteration_cost, vect_update_vf_for_slp)
(vect_analyze_loop_2): Don't treat pattern statements specially.
(vect_transform_loop): Likewise. Use vect_orig_stmt to find the
insertion point.
* tree-vect-slp.c (vect_detect_hybrid_slp): Expect pattern statements
to be in the statement list, without needing to follow
STMT_VINFO_RELATED_STMT. Remove PATTERN_DEF_SEQ handling.
* tree-vect-stmts.c (vect_analyze_stmt): Don't handle pattern
statements specially.
(vect_remove_dead_scalar_stmts): Ignore pattern statements.
* tree-vect-patterns.c (vect_set_pattern_stmt): Insert the pattern
statement into the vec_basic_block immediately before the statement
it replaces.
(append_pattern_def_seq): Likewise. If the original statement is
itself a pattern statement, associate the new one with the original
statement.
(vect_split_statement): Use append_pattern_def_seq to insert the
first pattern statement.
(vect_recog_vector_vector_shift_pattern): Remove mention of
STMT_VINFO_PATTERN_DEF_SEQ.
(adjust_bool_stmts): Get the last pattern statement from the
stmt_vec_info chain.
(vect_mark_pattern_stmts): Rename to...
(vect_replace_stmt_with_pattern): ...this. Remove the
PATTERN_DEF_SEQ handling and process only the pattern statement given.
Use append_pattern_def_seq when replacing a pattern statement with
another pattern statement, and use vec_basic_block::remove instead
of gsi_remove to remove the old one.
(vect_pattern_recog_1): Update accordingly. Remove PATTERN_DEF_SEQ
handling. On failure, remove any half-formed pattern sequence from
the vec_basic_block. Install the vector type in pattern statements
that don't yet have one.
(vect_pattern_recog): Iterate over statements that are added
by previous recognizers, but skipping those that have already
been replaced, or the main pattern statement in such a replacement.
Index: gcc/tree-vectorizer.h
===================================================================
*** gcc/tree-vectorizer.h 2018-07-30 12:32:46.658356275 +0100
--- gcc/tree-vectorizer.h 2018-07-30 12:32:49.898327734 +0100
*************** #define SLP_TREE_TWO_OPERATORS(S) (S)-
*** 172,178 ****
#define SLP_TREE_DEF_TYPE(S) (S)->def_type
/* Information about the phis and statements in a block that we're trying
! to vectorize, in their original order. */
class vec_basic_block
{
public:
--- 172,184 ----
#define SLP_TREE_DEF_TYPE(S) (S)->def_type
/* Information about the phis and statements in a block that we're trying
! to vectorize. This includes the phis and statements that were in the
! original scalar code, in their original order. It also includes any
! pattern statements that the vectorizer has created to replace some
! of the scalar ones. Such pattern statements come immediately before
! the statement that they replace; that is, all pattern statements P for
! which vect_orig_stmt (P) == S form a sequence that comes immediately
! before S. */
class vec_basic_block
{
public:
*************** struct _stmt_vec_info {
*** 870,880 ****
pattern). */
stmt_vec_info related_stmt;
- /* Used to keep a sequence of def stmts of a pattern stmt if such exists.
- The sequence is attached to the original statement rather than the
- pattern statement. */
- gimple_seq pattern_def_seq;
-
/* List of datarefs that are known to have the same alignment as the dataref
of this stmt. */
vec<dr_p> same_align_refs;
--- 876,881 ----
*************** #define STMT_VINFO_DR_INFO(S) \
*** 1048,1054 ****
#define STMT_VINFO_IN_PATTERN_P(S) (S)->in_pattern_p
#define STMT_VINFO_RELATED_STMT(S) (S)->related_stmt
- #define STMT_VINFO_PATTERN_DEF_SEQ(S) (S)->pattern_def_seq
#define STMT_VINFO_SAME_ALIGN_REFS(S) (S)->same_align_refs
#define STMT_VINFO_SIMD_CLONE_INFO(S) (S)->simd_clone_info
#define STMT_VINFO_DEF_TYPE(S) (S)->def_type
--- 1049,1054 ----
*************** is_pattern_stmt_p (stmt_vec_info stmt_in
*** 1176,1181 ****
--- 1176,1192 ----
return stmt_info->pattern_stmt_p;
}
+ /* Return TRUE if a statement represented by STMT_INFO is the final
+ statement in a pattern. */
+
+ static inline bool
+ is_main_pattern_stmt_p (stmt_vec_info stmt_info)
+ {
+ stmt_vec_info orig_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
+ return (is_pattern_stmt_p (stmt_info)
+ && STMT_VINFO_RELATED_STMT (orig_stmt_info) == stmt_info);
+ }
+
/* If STMT_INFO is a pattern statement, return the statement that it
replaces, otherwise return STMT_INFO itself. */
Index: gcc/tree-vect-loop.c
===================================================================
*** gcc/tree-vect-loop.c 2018-07-30 12:32:46.654356310 +0100
--- gcc/tree-vect-loop.c 2018-07-30 12:32:49.894327770 +0100
*************** Software Foundation; either version 3, o
*** 155,172 ****
static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *);
! /* Subroutine of vect_determine_vf_for_stmt that handles only one
! statement. VECTYPE_MAYBE_SET_P is true if STMT_VINFO_VECTYPE
! may already be set for general statements (not just data refs). */
static bool
! vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
! bool vectype_maybe_set_p,
! poly_uint64 *vf,
! vec<stmt_vec_info > *mask_producers)
{
gimple *stmt = stmt_info->stmt;
if ((!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
|| gimple_clobber_p (stmt))
--- 155,178 ----
static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *);
! /* Subroutine of vect_determine_vectorization_factor. Set the vector
! type of STMT_INFO and update the vectorization factor VF accordingly.
! If the statement produces a mask result whose vector type can only be
! calculated later, add it to MASK_PRODUCERS. Return true on success
! or false if something prevented vectorization. */
static bool
! vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
! vec<stmt_vec_info > *mask_producers)
{
gimple *stmt = stmt_info->stmt;
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: ");
+ dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
+ }
+
if ((!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
|| gimple_clobber_p (stmt))
*************** vect_determine_vf_for_stmt_1 (stmt_vec_i
*** 188,194 ****
that contain a data ref, or for "pattern-stmts" (stmts generated
by the vectorizer to represent/replace a certain idiom). */
gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
! || vectype_maybe_set_p)
&& STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
else if (stmt_vectype == boolean_type_node)
mask_producers->safe_push (stmt_info);
--- 194,200 ----
that contain a data ref, or for "pattern-stmts" (stmts generated
by the vectorizer to represent/replace a certain idiom). */
gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
! || is_pattern_stmt_p (stmt_info))
&& STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
else if (stmt_vectype == boolean_type_node)
mask_producers->safe_push (stmt_info);
*************** vect_determine_vf_for_stmt_1 (stmt_vec_i
*** 202,263 ****
return true;
}
- /* Subroutine of vect_determine_vectorization_factor. Set the vector
- types of STMT_INFO and all attached pattern statements and update
- the vectorization factor VF accordingly. If some of the statements
- produce a mask result whose vector type can only be calculated later,
- add them to MASK_PRODUCERS. Return true on success or false if
- something prevented vectorization. */
-
- static bool
- vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
- vec<stmt_vec_info > *mask_producers)
- {
- vec_info *vinfo = stmt_info->vinfo;
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
- }
- if (!vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers))
- return false;
-
- if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && STMT_VINFO_RELATED_STMT (stmt_info))
- {
- gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
- stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
-
- /* If a pattern statement has def stmts, analyze them too. */
- for (gimple_stmt_iterator si = gsi_start (pattern_def_seq);
- !gsi_end_p (si); gsi_next (&si))
- {
- stmt_vec_info def_stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern def stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- def_stmt_info->stmt, 0);
- }
- if (!vect_determine_vf_for_stmt_1 (def_stmt_info, true,
- vf, mask_producers))
- return false;
- }
-
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
- }
- if (!vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers))
- return false;
- }
-
- return true;
- }
-
/* Function vect_determine_vectorization_factor
Determine the vectorization factor (VF). VF is the number of data elements
--- 208,213 ----
*************** vect_compute_single_scalar_iteration_cos
*** 1078,1086 ****
/* Skip stmts that are not vectorized inside the loop. */
if (stmt_info
&& !STMT_VINFO_RELEVANT_P (stmt_info)
! && (!STMT_VINFO_LIVE_P (stmt_info)
! || !VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
! && !STMT_VINFO_IN_PATTERN_P (stmt_info))
continue;
vect_cost_for_stmt kind;
--- 1028,1035 ----
/* Skip stmts that are not vectorized inside the loop. */
if (stmt_info
&& !STMT_VINFO_RELEVANT_P (stmt_info)
! && (!VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))
! || !STMT_VINFO_LIVE_P (stmt_info)))
continue;
vect_cost_for_stmt kind;
*************** vect_update_vf_for_slp (loop_vec_info lo
*** 1394,1407 ****
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! {
! stmt_vec_info final_info = vect_stmt_to_vectorize (stmt_info);
! if ((STMT_VINFO_RELEVANT_P (final_info)
! || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (final_info)))
! && !PURE_SLP_STMT (final_info))
! /* STMT needs both SLP and loop-based vectorization. */
! only_slp_in_loop = false;
! }
if (only_slp_in_loop)
{
--- 1343,1353 ----
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! if ((STMT_VINFO_RELEVANT_P (stmt_info)
! || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
! && !PURE_SLP_STMT (stmt_info))
! /* STMT needs both SLP and loop-based vectorization. */
! only_slp_in_loop = false;
if (only_slp_in_loop)
{
*************** vect_analyze_loop_2 (loop_vec_info loop_
*** 2164,2181 ****
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! {
! STMT_SLP_TYPE (stmt_info) = loop_vect;
! if (STMT_VINFO_IN_PATTERN_P (stmt_info))
! {
! gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
! STMT_SLP_TYPE (STMT_VINFO_RELATED_STMT (stmt_info)) = loop_vect;
! for (gimple_stmt_iterator pi = gsi_start (pattern_def_seq);
! !gsi_end_p (pi); gsi_next (&pi))
! STMT_SLP_TYPE (loop_vinfo->lookup_stmt (gsi_stmt (pi)))
! = loop_vect;
! }
! }
/* Free optimized alias test DDRS. */
LOOP_VINFO_LOWER_BOUNDS (loop_vinfo).truncate (0);
--- 2110,2116 ----
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! STMT_SLP_TYPE (stmt_info) = loop_vect;
/* Free optimized alias test DDRS. */
LOOP_VINFO_LOWER_BOUNDS (loop_vinfo).truncate (0);
*************** vect_transform_loop (loop_vec_info loop_
*** 8371,8392 ****
loop_vinfo->remove_stmt (stmt_info);
else
{
! gimple_stmt_iterator si = gsi_for_stmt (stmt_info->stmt);
! if (STMT_VINFO_IN_PATTERN_P (stmt_info))
! {
! gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
! for (gimple_stmt_iterator subsi = gsi_start (def_seq);
! !gsi_end_p (subsi); gsi_next (&subsi))
! {
! stmt_vec_info pat_stmt_info
! = loop_vinfo->lookup_stmt (gsi_stmt (subsi));
! vect_transform_loop_stmt (loop_vinfo, pat_stmt_info,
! &si);
! }
! stmt_vec_info pat_stmt_info
! = STMT_VINFO_RELATED_STMT (stmt_info);
! vect_transform_loop_stmt (loop_vinfo, pat_stmt_info, &si);
! }
vect_transform_loop_stmt (loop_vinfo, stmt_info, &si);
}
}
--- 8306,8313 ----
loop_vinfo->remove_stmt (stmt_info);
else
{
! stmt_vec_info place = vect_orig_stmt (stmt_info);
! gimple_stmt_iterator si = gsi_for_stmt (place->stmt);
vect_transform_loop_stmt (loop_vinfo, stmt_info, &si);
}
}
Index: gcc/tree-vect-slp.c
===================================================================
*** gcc/tree-vect-slp.c 2018-07-30 12:32:46.654356310 +0100
--- gcc/tree-vect-slp.c 2018-07-30 12:32:49.894327770 +0100
*************** vect_detect_hybrid_slp (loop_vec_info lo
*** 2411,2428 ****
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! if (STMT_VINFO_IN_PATTERN_P (stmt_info))
{
walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
wi.info = loop_vinfo;
! gimple_stmt_iterator gsi2
! = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info)->stmt);
! walk_gimple_stmt (&gsi2, vect_detect_hybrid_slp_2,
vect_detect_hybrid_slp_1, &wi);
- walk_gimple_seq (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
- vect_detect_hybrid_slp_2,
- vect_detect_hybrid_slp_1, &wi);
}
/* Then walk the SLP instance trees marking stmts with uses in
--- 2411,2424 ----
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! if (is_pattern_stmt_p (stmt_info))
{
walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
wi.info = loop_vinfo;
! gimple_stmt_iterator gsi = gsi_for_stmt (stmt_info->stmt);
! walk_gimple_stmt (&gsi, vect_detect_hybrid_slp_2,
vect_detect_hybrid_slp_1, &wi);
}
/* Then walk the SLP instance trees marking stmts with uses in
Index: gcc/tree-vect-stmts.c
===================================================================
*** gcc/tree-vect-stmts.c 2018-07-30 12:32:46.658356275 +0100
--- gcc/tree-vect-stmts.c 2018-07-30 12:32:49.898327734 +0100
*************** vect_analyze_stmt (stmt_vec_info stmt_in
*** 9384,9394 ****
slp_tree node, slp_instance node_instance,
stmt_vector_for_cost *cost_vec)
{
- vec_info *vinfo = stmt_info->vinfo;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
bool ok;
- gimple_seq pattern_def_seq;
if (dump_enabled_p ())
{
--- 9384,9392 ----
*************** vect_analyze_stmt (stmt_vec_info stmt_in
*** 9405,9498 ****
return false;
}
- if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && node == NULL
- && (pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info)))
- {
- gimple_stmt_iterator si;
-
- for (si = gsi_start (pattern_def_seq); !gsi_end_p (si); gsi_next (&si))
- {
- stmt_vec_info pattern_def_stmt_info
- = vinfo->lookup_stmt (gsi_stmt (si));
- if (STMT_VINFO_RELEVANT_P (pattern_def_stmt_info)
- || STMT_VINFO_LIVE_P (pattern_def_stmt_info))
- {
- /* Analyze def stmt of STMT if it's a pattern stmt. */
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern def statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- pattern_def_stmt_info->stmt, 0);
- }
-
- if (!vect_analyze_stmt (pattern_def_stmt_info,
- need_to_vectorize, node, node_instance,
- cost_vec))
- return false;
- }
- }
- }
-
/* Skip stmts that do not need to be vectorized. In loops this is expected
to include:
- the COND_EXPR which is the loop exit condition
- any LABEL_EXPRs in the loop
- computations that are used only for array indexing or loop control.
In basic blocks we only analyze statements that are a part of some SLP
! instance, therefore, all the statements are relevant.
!
! Pattern statement needs to be analyzed instead of the original statement
! if the original statement is not relevant. Otherwise, we analyze both
! statements. In basic blocks we are called from some SLP instance
! traversal, don't analyze pattern stmts instead, the pattern stmts
! already will be part of SLP instance. */
- stmt_vec_info pattern_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
{
- if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && pattern_stmt_info
- && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
- || STMT_VINFO_LIVE_P (pattern_stmt_info)))
- {
- /* Analyze PATTERN_STMT instead of the original stmt. */
- stmt_info = pattern_stmt_info;
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
- }
- }
- else
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n");
-
- return true;
- }
- }
- else if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && node == NULL
- && pattern_stmt_info
- && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
- || STMT_VINFO_LIVE_P (pattern_stmt_info)))
- {
- /* Analyze PATTERN_STMT too. */
if (dump_enabled_p ())
! {
! dump_printf_loc (MSG_NOTE, vect_location,
! "==> examining pattern statement: ");
! dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt_info->stmt, 0);
! }
!
! if (!vect_analyze_stmt (pattern_stmt_info, need_to_vectorize, node,
! node_instance, cost_vec))
! return false;
! }
switch (STMT_VINFO_DEF_TYPE (stmt_info))
{
--- 9403,9423 ----
return false;
}
/* Skip stmts that do not need to be vectorized. In loops this is expected
to include:
- the COND_EXPR which is the loop exit condition
- any LABEL_EXPRs in the loop
- computations that are used only for array indexing or loop control.
In basic blocks we only analyze statements that are a part of some SLP
! instance, therefore, all the statements are relevant. */
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
{
if (dump_enabled_p ())
! dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n");
! return true;
! }
switch (STMT_VINFO_DEF_TYPE (stmt_info))
{
*************** vect_remove_dead_scalar_stmts (vec_info
*** 10915,10921 ****
stmt_info = prev_stmt_info)
{
prev_stmt_info = stmt_info->prev;
! vect_maybe_remove_scalar_stmt (stmt_info);
}
}
}
--- 10840,10847 ----
stmt_info = prev_stmt_info)
{
prev_stmt_info = stmt_info->prev;
! if (!is_pattern_stmt_p (stmt_info))
! vect_maybe_remove_scalar_stmt (stmt_info);
}
}
}
Index: gcc/tree-vect-patterns.c
===================================================================
*** gcc/tree-vect-patterns.c 2018-07-30 12:32:42.786390386 +0100
--- gcc/tree-vect-patterns.c 2018-07-30 12:32:49.894327770 +0100
*************** vect_init_pattern_stmt (gimple *pattern_
*** 125,151 ****
vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
tree vectype)
{
! STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
! STMT_VINFO_RELATED_STMT (orig_stmt_info)
= vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype);
}
! /* Add NEW_STMT to STMT_INFO's pattern definition statements. If VECTYPE
! is nonnull, record that NEW_STMT's vector type is VECTYPE, which might
! be different from the vector type of the final pattern statement. */
static inline void
append_pattern_def_seq (stmt_vec_info stmt_info, gimple *new_stmt,
tree vectype = NULL_TREE)
{
! vec_info *vinfo = stmt_info->vinfo;
! if (vectype)
! {
! stmt_vec_info new_stmt_info = vinfo->add_stmt (new_stmt);
! STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
! }
! gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
! new_stmt);
}
/* The caller wants to perform new operations on vect_external variable
--- 125,150 ----
vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
tree vectype)
{
! stmt_vec_info pattern_stmt_info
= vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype);
+ orig_stmt_info->block->add_before (pattern_stmt_info, orig_stmt_info);
+ STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
+ STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt_info;
}
! /* Add NEW_STMT to the pattern statements that replace STMT_INFO.
! If VECTYPE is nonnull, record that NEW_STMT's vector type is VECTYPE,
! which might be different from the vector type of the final pattern
! statement. */
static inline void
append_pattern_def_seq (stmt_vec_info stmt_info, gimple *new_stmt,
tree vectype = NULL_TREE)
{
! stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
! stmt_vec_info new_stmt_info
! = vect_init_pattern_stmt (new_stmt, orig_stmt_info, vectype);
! stmt_info->block->add_before (new_stmt_info, stmt_info);
}
/* The caller wants to perform new operations on vect_external variable
*************** vect_split_statement (stmt_vec_info stmt
*** 633,643 ****
{
if (is_pattern_stmt_p (stmt2_info))
{
- /* STMT2_INFO is part of a pattern. Get the statement to which
- the pattern is attached. */
- stmt_vec_info orig_stmt2_info = STMT_VINFO_RELATED_STMT (stmt2_info);
- vect_init_pattern_stmt (stmt1, orig_stmt2_info, vectype);
-
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
--- 632,637 ----
*************** vect_split_statement (stmt_vec_info stmt
*** 645,650 ****
--- 639,647 ----
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
}
+ /* Insert STMT1_INFO before STMT2_INFO. */
+ append_pattern_def_seq (stmt2_info, stmt1, vectype);
+
/* Since STMT2_INFO is a pattern statement, we can change it
in-situ without worrying about changing the code for the
containing block. */
*************** vect_split_statement (stmt_vec_info stmt
*** 658,675 ****
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
}
- gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt2_info);
- if (STMT_VINFO_RELATED_STMT (orig_stmt2_info) == stmt2_info)
- /* STMT2_INFO is the actual pattern statement. Add STMT1
- to the end of the definition sequence. */
- gimple_seq_add_stmt_without_update (def_seq, stmt1);
- else
- {
- /* STMT2_INFO belongs to the definition sequence. Insert STMT1
- before it. */
- gimple_stmt_iterator gsi = gsi_for_stmt (stmt2_info->stmt, def_seq);
- gsi_insert_before_without_update (&gsi, stmt1, GSI_SAME_STMT);
- }
return true;
}
else
--- 655,660 ----
*************** vect_split_statement (stmt_vec_info stmt
*** 689,698 ****
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
}
! /* Add STMT1 as a singleton pattern definition sequence. */
! gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (stmt2_info);
! vect_init_pattern_stmt (stmt1, stmt2_info, vectype);
! gimple_seq_add_stmt_without_update (def_seq, stmt1);
/* Build the second of the two pattern statements. */
tree new_lhs = vect_recog_temp_ssa_var (lhs_type, NULL);
--- 674,681 ----
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
}
! /* Insert STMT1_INFO before STMT2_INFO. */
! append_pattern_def_seq (stmt2_info, stmt1, vectype);
/* Build the second of the two pattern statements. */
tree new_lhs = vect_recog_temp_ssa_var (lhs_type, NULL);
*************** vect_recog_rotate_pattern (stmt_vec_info
*** 2164,2170 ****
i.e. the shift/rotate stmt. The original stmt (S3) is replaced
with a shift/rotate which has same type on both operands, in the
second case just b_T op c_T, in the first case with added cast
! from a_t to c_T in STMT_VINFO_PATTERN_DEF_SEQ.
Output:
--- 2147,2153 ----
i.e. the shift/rotate stmt. The original stmt (S3) is replaced
with a shift/rotate which has same type on both operands, in the
second case just b_T op c_T, in the first case with added cast
! from a_t to c_T beforehand.
Output:
*************** adjust_bool_stmts (hash_set <gimple *> &
*** 3518,3526 ****
adjust_bool_pattern (gimple_assign_lhs (bool_stmts[i]),
out_type, stmt_info, defs);
! /* Pop the last pattern seq stmt and install it as pattern root for STMT. */
! gimple *pattern_stmt
! = gimple_seq_last_stmt (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
return gimple_assign_lhs (pattern_stmt);
}
--- 3501,3508 ----
adjust_bool_pattern (gimple_assign_lhs (bool_stmts[i]),
out_type, stmt_info, defs);
! /* Return the result of the last statement we emitted. */
! gimple *pattern_stmt = stmt_info->prev->stmt;
return gimple_assign_lhs (pattern_stmt);
}
*************** static vect_recog_func vect_vect_recog_f
*** 4676,4689 ****
const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
! /* Mark statements that are involved in a pattern. */
static inline void
! vect_mark_pattern_stmts (stmt_vec_info orig_stmt_info, gimple *pattern_stmt,
! tree pattern_vectype)
{
- gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
-
gimple *orig_pattern_stmt = NULL;
if (is_pattern_stmt_p (orig_stmt_info))
{
--- 4658,4671 ----
const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
! /* Replace ORIG_STMT_INFO with PATTERN_STMT, using PATTERN_VECTYPE as
! the vector type for PATTERN_STMT. */
static inline void
! vect_replace_stmt_with_pattern (stmt_vec_info orig_stmt_info,
! gimple *pattern_stmt,
! tree pattern_vectype)
{
gimple *orig_pattern_stmt = NULL;
if (is_pattern_stmt_p (orig_stmt_info))
{
*************** vect_mark_pattern_stmts (stmt_vec_info o
*** 4710,4741 ****
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
}
- /* Switch to the statement that ORIG replaces. */
- orig_stmt_info = STMT_VINFO_RELATED_STMT (orig_stmt_info);
-
/* We shouldn't be replacing the main pattern statement. */
! gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info)->stmt
! != orig_pattern_stmt);
! }
! if (def_seq)
! for (gimple_stmt_iterator si = gsi_start (def_seq);
! !gsi_end_p (si); gsi_next (&si))
! vect_init_pattern_stmt (gsi_stmt (si), orig_stmt_info, pattern_vectype);
!
! if (orig_pattern_stmt)
! {
! vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
!
! /* Insert all the new pattern statements before the original one. */
! gimple_seq *orig_def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
! gimple_stmt_iterator gsi = gsi_for_stmt (orig_pattern_stmt,
! orig_def_seq);
! gsi_insert_seq_before_without_update (&gsi, def_seq, GSI_SAME_STMT);
! gsi_insert_before_without_update (&gsi, pattern_stmt, GSI_SAME_STMT);
/* Remove the pattern statement that this new pattern replaces. */
! gsi_remove (&gsi, false);
}
else
vect_set_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
--- 4692,4705 ----
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
}
/* We shouldn't be replacing the main pattern statement. */
! gcc_assert (!is_main_pattern_stmt_p (orig_stmt_info));
! /* Insert the new pattern statement before the original one. */
! append_pattern_def_seq (orig_stmt_info, pattern_stmt, pattern_vectype);
/* Remove the pattern statement that this new pattern replaces. */
! orig_stmt_info->block->remove (orig_stmt_info);
}
else
vect_set_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
*************** vect_mark_pattern_stmts (stmt_vec_info o
*** 4762,4791 ****
static void
vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info)
{
- vec_info *vinfo = stmt_info->vinfo;
gimple *pattern_stmt;
loop_vec_info loop_vinfo;
tree pattern_vectype;
! /* If this statement has already been replaced with pattern statements,
! leave the original statement alone, since the first match wins.
! Instead try to match against the definition statements that feed
! the main pattern statement. */
! if (STMT_VINFO_IN_PATTERN_P (stmt_info))
! {
! gimple_stmt_iterator gsi;
! for (gsi = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
! !gsi_end_p (gsi); gsi_next (&gsi))
! vect_pattern_recog_1 (recog_func, vinfo->lookup_stmt (gsi_stmt (gsi)));
! return;
! }
!
! gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
pattern_stmt = recog_func->fn (stmt_info, &pattern_vectype);
if (!pattern_stmt)
{
! /* Clear any half-formed pattern definition sequence. */
! STMT_VINFO_PATTERN_DEF_SEQ (stmt_info) = NULL;
return;
}
--- 4726,4742 ----
static void
vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info)
{
gimple *pattern_stmt;
loop_vec_info loop_vinfo;
tree pattern_vectype;
! stmt_vec_info prev_stmt_info = stmt_info->prev;
pattern_stmt = recog_func->fn (stmt_info, &pattern_vectype);
if (!pattern_stmt)
{
! /* Delete any half-formed pattern sequence. */
! while (stmt_info->prev != prev_stmt_info)
! stmt_info->block->remove (prev_stmt_info);
return;
}
*************** vect_pattern_recog_1 (vect_recog_func *r
*** 4800,4807 ****
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
}
/* Mark the stmts that are involved in the pattern. */
! vect_mark_pattern_stmts (stmt_info, pattern_stmt, pattern_vectype);
/* Patterns cannot be vectorized using SLP, because they change the order of
computation. */
--- 4751,4765 ----
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
}
+ /* Install the vector type in pattern definition statements that
+ don't yet have one. */
+ for (stmt_vec_info pat_stmt_info = stmt_info->prev;
+ pat_stmt_info != prev_stmt_info; pat_stmt_info = pat_stmt_info->prev)
+ if (!STMT_VINFO_VECTYPE (pat_stmt_info))
+ STMT_VINFO_VECTYPE (pat_stmt_info) = pattern_vectype;
+
/* Mark the stmts that are involved in the pattern. */
! vect_replace_stmt_with_pattern (stmt_info, pattern_stmt, pattern_vectype);
/* Patterns cannot be vectorized using SLP, because they change the order of
computation. */
*************** vect_pattern_recog (vec_info *vinfo)
*** 4903,4910 ****
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! if (STMT_VINFO_VECTORIZABLE (stmt_info))
! /* Scan over all generic vect_recog_xxx_pattern functions. */
! for (unsigned int j = 0; j < NUM_PATTERNS; j++)
! vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], stmt_info);
}
--- 4861,4887 ----
vec_basic_block *vec_bb;
FOR_EACH_VEC_ELT (vinfo->blocks, i, vec_bb)
FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
! {
! stmt_vec_info begin_prev = stmt_info->prev;
! if (STMT_VINFO_VECTORIZABLE (stmt_info))
! /* Scan over all generic vect_recog_xxx_pattern functions. */
! for (unsigned int j = 0; j < NUM_PATTERNS; j++)
! {
! stmt_vec_info curr_prev;
! /* Scan over STMT_INFO and any pattern definition statements
! that were introduced by previous recognizers. */
! for (stmt_vec_info curr_info = stmt_info;
! curr_info != begin_prev; curr_info = curr_prev)
! {
! curr_prev = curr_info->prev;
! /* The first match wins, so skip statements that have
! already been replaced, and the final statement with
! which they were replaced. */
! if (!STMT_VINFO_IN_PATTERN_P (curr_info)
! && !is_main_pattern_stmt_p (curr_info))
! vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j],
! curr_info);
! }
! }
! }
}