[11/46] Pass back a stmt_vec_info from vect_is_simple_use

This patch makes vect_is_simple_use pass back a stmt_vec_info to
those callers that want it.  Most users only need the stmt_vec_info
but some need the gimple stmt too.

It's probably high time we added a class to represent "simple operands"
instead, but I have a separate series that tries to clean up how
operands are handled (with a view to allowing mixed vector sizes).

2018-07-31  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* tree-vectorizer.h (vect_is_simple_use): Add an optional
	stmt_vec_info * parameter before the optional gimple **.
	* tree-vect-stmts.c (vect_is_simple_use): Likewise.
	(process_use, vect_get_vec_def_for_operand_1): Update callers.
	(vect_get_vec_def_for_operand, vectorizable_shift): Likewise.
	* tree-vect-loop.c (vectorizable_reduction): Likewise.
	(vectorizable_live_operation): Likewise.
	* tree-vect-patterns.c (type_conversion_p): Likewise.
	(vect_look_through_possible_promotion): Likewise.
	(vect_recog_rotate_pattern): Likewise.
	* tree-vect-slp.c (vect_get_and_check_slp_defs): Likewise.

From-SVN: r263126
This commit is contained in:
Richard Sandiford 2018-07-31 14:22:01 +00:00 committed by Richard Sandiford
parent dbe1b84664
commit fef96d8e2a
6 changed files with 90 additions and 75 deletions

View File

@ -1,3 +1,17 @@
2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
* tree-vectorizer.h (vect_is_simple_use): Add an optional
stmt_vec_info * parameter before the optional gimple **.
* tree-vect-stmts.c (vect_is_simple_use): Likewise.
(process_use, vect_get_vec_def_for_operand_1): Update callers.
(vect_get_vec_def_for_operand, vectorizable_shift): Likewise.
* tree-vect-loop.c (vectorizable_reduction): Likewise.
(vectorizable_live_operation): Likewise.
* tree-vect-patterns.c (type_conversion_p): Likewise.
(vect_look_through_possible_promotion): Likewise.
(vect_recog_rotate_pattern): Likewise.
* tree-vect-slp.c (vect_get_and_check_slp_defs): Likewise.
2018-07-31 Richard Sandiford <richard.sandiford@arm.com> 2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
* tree-vectorizer.h (stmt_vec_info): Temporarily change from * tree-vectorizer.h (stmt_vec_info): Temporarily change from

View File

@ -6090,7 +6090,6 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
int op_type; int op_type;
optab optab; optab optab;
tree new_temp = NULL_TREE; tree new_temp = NULL_TREE;
gimple *def_stmt;
enum vect_def_type dt, cond_reduc_dt = vect_unknown_def_type; enum vect_def_type dt, cond_reduc_dt = vect_unknown_def_type;
gimple *cond_reduc_def_stmt = NULL; gimple *cond_reduc_def_stmt = NULL;
enum tree_code cond_reduc_op_code = ERROR_MARK; enum tree_code cond_reduc_op_code = ERROR_MARK;
@ -6324,13 +6323,14 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (i == 0 && code == COND_EXPR) if (i == 0 && code == COND_EXPR)
continue; continue;
is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, stmt_vec_info def_stmt_info;
&dts[i], &tem, &def_stmt); is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, &dts[i], &tem,
&def_stmt_info);
dt = dts[i]; dt = dts[i];
gcc_assert (is_simple_use); gcc_assert (is_simple_use);
if (dt == vect_reduction_def) if (dt == vect_reduction_def)
{ {
reduc_def_stmt = def_stmt; reduc_def_stmt = def_stmt_info;
reduc_index = i; reduc_index = i;
continue; continue;
} }
@ -6352,11 +6352,11 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
return false; return false;
if (dt == vect_nested_cycle) if (dt == vect_nested_cycle)
{ {
found_nested_cycle_def = true; found_nested_cycle_def = true;
reduc_def_stmt = def_stmt; reduc_def_stmt = def_stmt_info;
reduc_index = i; reduc_index = i;
} }
if (i == 1 && code == COND_EXPR) if (i == 1 && code == COND_EXPR)
{ {
@ -6367,11 +6367,11 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
cond_reduc_val = ops[i]; cond_reduc_val = ops[i];
} }
if (dt == vect_induction_def if (dt == vect_induction_def
&& def_stmt != NULL && def_stmt_info
&& is_nonwrapping_integer_induction (def_stmt, loop)) && is_nonwrapping_integer_induction (def_stmt_info, loop))
{ {
cond_reduc_dt = dt; cond_reduc_dt = dt;
cond_reduc_def_stmt = def_stmt; cond_reduc_def_stmt = def_stmt_info;
} }
} }
} }
@ -7958,7 +7958,7 @@ vectorizable_live_operation (gimple *stmt,
else else
{ {
enum vect_def_type dt = STMT_VINFO_DEF_TYPE (stmt_info); enum vect_def_type dt = STMT_VINFO_DEF_TYPE (stmt_info);
vec_lhs = vect_get_vec_def_for_operand_1 (stmt, dt); vec_lhs = vect_get_vec_def_for_operand_1 (stmt_info, dt);
gcc_checking_assert (ncopies == 1 gcc_checking_assert (ncopies == 1
|| !LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)); || !LOOP_VINFO_FULLY_MASKED_P (loop_vinfo));

View File

@ -250,7 +250,9 @@ type_conversion_p (tree name, gimple *use_stmt, bool check_sign,
enum vect_def_type dt; enum vect_def_type dt;
stmt_vinfo = vinfo_for_stmt (use_stmt); stmt_vinfo = vinfo_for_stmt (use_stmt);
if (!vect_is_simple_use (name, stmt_vinfo->vinfo, &dt, def_stmt)) stmt_vec_info def_stmt_info;
if (!vect_is_simple_use (name, stmt_vinfo->vinfo, &dt, &def_stmt_info,
def_stmt))
return false; return false;
if (dt != vect_internal_def if (dt != vect_internal_def
@ -371,9 +373,10 @@ vect_look_through_possible_promotion (vec_info *vinfo, tree op,
while (TREE_CODE (op) == SSA_NAME && INTEGRAL_TYPE_P (op_type)) while (TREE_CODE (op) == SSA_NAME && INTEGRAL_TYPE_P (op_type))
{ {
/* See whether OP is simple enough to vectorize. */ /* See whether OP is simple enough to vectorize. */
stmt_vec_info def_stmt_info;
gimple *def_stmt; gimple *def_stmt;
vect_def_type dt; vect_def_type dt;
if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt)) if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt_info, &def_stmt))
break; break;
/* If OP is the input of a demotion, skip over it to see whether /* If OP is the input of a demotion, skip over it to see whether
@ -407,17 +410,15 @@ vect_look_through_possible_promotion (vec_info *vinfo, tree op,
the cast is potentially vectorizable. */ the cast is potentially vectorizable. */
if (!def_stmt) if (!def_stmt)
break; break;
if (dt == vect_internal_def) caster = def_stmt_info;
{
caster = vinfo_for_stmt (def_stmt); /* Ignore pattern statements, since we don't link uses for them. */
/* Ignore pattern statements, since we don't link uses for them. */ if (caster
if (single_use_p && single_use_p
&& !STMT_VINFO_RELATED_STMT (caster) && !STMT_VINFO_RELATED_STMT (caster)
&& !has_single_use (res)) && !has_single_use (res))
*single_use_p = false; *single_use_p = false;
}
else
caster = NULL;
gassign *assign = dyn_cast <gassign *> (def_stmt); gassign *assign = dyn_cast <gassign *> (def_stmt);
if (!assign || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))) if (!assign || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
break; break;
@ -1988,7 +1989,8 @@ vect_recog_rotate_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
|| !TYPE_UNSIGNED (type)) || !TYPE_UNSIGNED (type))
return NULL; return NULL;
if (!vect_is_simple_use (oprnd1, vinfo, &dt, &def_stmt)) stmt_vec_info def_stmt_info;
if (!vect_is_simple_use (oprnd1, vinfo, &dt, &def_stmt_info, &def_stmt))
return NULL; return NULL;
if (dt != vect_internal_def if (dt != vect_internal_def

View File

@ -303,7 +303,6 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap,
gimple *stmt = stmts[stmt_num]; gimple *stmt = stmts[stmt_num];
tree oprnd; tree oprnd;
unsigned int i, number_of_oprnds; unsigned int i, number_of_oprnds;
gimple *def_stmt;
enum vect_def_type dt = vect_uninitialized_def; enum vect_def_type dt = vect_uninitialized_def;
bool pattern = false; bool pattern = false;
slp_oprnd_info oprnd_info; slp_oprnd_info oprnd_info;
@ -357,7 +356,8 @@ again:
oprnd_info = (*oprnds_info)[i]; oprnd_info = (*oprnds_info)[i];
if (!vect_is_simple_use (oprnd, vinfo, &dt, &def_stmt)) stmt_vec_info def_stmt_info;
if (!vect_is_simple_use (oprnd, vinfo, &dt, &def_stmt_info))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
@ -370,13 +370,10 @@ again:
return -1; return -1;
} }
/* Check if DEF_STMT is a part of a pattern in LOOP and get the def stmt /* Check if DEF_STMT_INFO is a part of a pattern in LOOP and get
from the pattern. Check that all the stmts of the node are in the the def stmt from the pattern. Check that all the stmts of the
pattern. */ node are in the pattern. */
if (def_stmt && gimple_bb (def_stmt) if (def_stmt_info && is_pattern_stmt_p (def_stmt_info))
&& vect_stmt_in_region_p (vinfo, def_stmt)
&& vinfo_for_stmt (def_stmt)
&& is_pattern_stmt_p (vinfo_for_stmt (def_stmt)))
{ {
pattern = true; pattern = true;
if (!first && !oprnd_info->first_pattern if (!first && !oprnd_info->first_pattern
@ -405,7 +402,7 @@ again:
return 1; return 1;
} }
dt = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)); dt = STMT_VINFO_DEF_TYPE (def_stmt_info);
if (dt == vect_unknown_def_type) if (dt == vect_unknown_def_type)
{ {
@ -415,7 +412,7 @@ again:
return -1; return -1;
} }
switch (gimple_code (def_stmt)) switch (gimple_code (def_stmt_info->stmt))
{ {
case GIMPLE_PHI: case GIMPLE_PHI:
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
@ -499,7 +496,7 @@ again:
case vect_reduction_def: case vect_reduction_def:
case vect_induction_def: case vect_induction_def:
case vect_internal_def: case vect_internal_def:
oprnd_info->def_stmts.quick_push (def_stmt); oprnd_info->def_stmts.quick_push (def_stmt_info);
break; break;
default: default:

View File

@ -459,11 +459,9 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
enum vect_relevant relevant, vec<gimple *> *worklist, enum vect_relevant relevant, vec<gimple *> *worklist,
bool force) bool force)
{ {
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt); stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
stmt_vec_info dstmt_vinfo; stmt_vec_info dstmt_vinfo;
basic_block bb, def_bb; basic_block bb, def_bb;
gimple *def_stmt;
enum vect_def_type dt; enum vect_def_type dt;
/* case 1: we are only interested in uses that need to be vectorized. Uses /* case 1: we are only interested in uses that need to be vectorized. Uses
@ -471,7 +469,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
if (!force && !exist_non_indexing_operands_for_use_p (use, stmt)) if (!force && !exist_non_indexing_operands_for_use_p (use, stmt))
return true; return true;
if (!vect_is_simple_use (use, loop_vinfo, &dt, &def_stmt)) if (!vect_is_simple_use (use, loop_vinfo, &dt, &dstmt_vinfo))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@ -479,27 +477,20 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
return false; return false;
} }
if (!def_stmt || gimple_nop_p (def_stmt)) if (!dstmt_vinfo)
return true; return true;
def_bb = gimple_bb (def_stmt); def_bb = gimple_bb (dstmt_vinfo->stmt);
if (!flow_bb_inside_loop_p (loop, def_bb))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "def_stmt is out of loop.\n");
return true;
}
/* case 2: A reduction phi (STMT) defined by a reduction stmt (DEF_STMT). /* case 2: A reduction phi (STMT) defined by a reduction stmt (DSTMT_VINFO).
DEF_STMT must have already been processed, because this should be the DSTMT_VINFO must have already been processed, because this should be the
only way that STMT, which is a reduction-phi, was put in the worklist, only way that STMT, which is a reduction-phi, was put in the worklist,
as there should be no other uses for DEF_STMT in the loop. So we just as there should be no other uses for DSTMT_VINFO in the loop. So we just
check that everything is as expected, and we are done. */ check that everything is as expected, and we are done. */
dstmt_vinfo = vinfo_for_stmt (def_stmt);
bb = gimple_bb (stmt); bb = gimple_bb (stmt);
if (gimple_code (stmt) == GIMPLE_PHI if (gimple_code (stmt) == GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def && STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
&& gimple_code (def_stmt) != GIMPLE_PHI && gimple_code (dstmt_vinfo->stmt) != GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (dstmt_vinfo) == vect_reduction_def && STMT_VINFO_DEF_TYPE (dstmt_vinfo) == vect_reduction_def
&& bb->loop_father == def_bb->loop_father) && bb->loop_father == def_bb->loop_father)
{ {
@ -514,7 +505,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
/* case 3a: outer-loop stmt defining an inner-loop stmt: /* case 3a: outer-loop stmt defining an inner-loop stmt:
outer-loop-header-bb: outer-loop-header-bb:
d = def_stmt d = dstmt_vinfo
inner-loop: inner-loop:
stmt # use (d) stmt # use (d)
outer-loop-tail-bb: outer-loop-tail-bb:
@ -554,7 +545,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
outer-loop-header-bb: outer-loop-header-bb:
... ...
inner-loop: inner-loop:
d = def_stmt d = dstmt_vinfo
outer-loop-tail-bb (or outer-loop-exit-bb in double reduction): outer-loop-tail-bb (or outer-loop-exit-bb in double reduction):
stmt # use (d) */ stmt # use (d) */
else if (flow_loop_nested_p (bb->loop_father, def_bb->loop_father)) else if (flow_loop_nested_p (bb->loop_father, def_bb->loop_father))
@ -601,7 +592,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
} }
vect_mark_relevant (worklist, def_stmt, relevant, false); vect_mark_relevant (worklist, dstmt_vinfo, relevant, false);
return true; return true;
} }
@ -1563,7 +1554,9 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
dump_printf (MSG_NOTE, "\n"); dump_printf (MSG_NOTE, "\n");
} }
is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt, &def_stmt); stmt_vec_info def_stmt_info;
is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt,
&def_stmt_info, &def_stmt);
gcc_assert (is_simple_use); gcc_assert (is_simple_use);
if (def_stmt && dump_enabled_p ()) if (def_stmt && dump_enabled_p ())
{ {
@ -1588,7 +1581,7 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
return vect_init_vector (stmt, op, vector_type, NULL); return vect_init_vector (stmt, op, vector_type, NULL);
} }
else else
return vect_get_vec_def_for_operand_1 (def_stmt, dt); return vect_get_vec_def_for_operand_1 (def_stmt_info, dt);
} }
@ -5479,7 +5472,9 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
return false; return false;
op1 = gimple_assign_rhs2 (stmt); op1 = gimple_assign_rhs2 (stmt);
if (!vect_is_simple_use (op1, vinfo, &dt[1], &op1_vectype)) stmt_vec_info op1_def_stmt_info;
if (!vect_is_simple_use (op1, vinfo, &dt[1], &op1_vectype,
&op1_def_stmt_info))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@ -5524,12 +5519,8 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
/* If the shift amount is computed by a pattern stmt we cannot /* If the shift amount is computed by a pattern stmt we cannot
use the scalar amount directly thus give up and use a vector use the scalar amount directly thus give up and use a vector
shift. */ shift. */
if (dt[1] == vect_internal_def) if (op1_def_stmt_info && is_pattern_stmt_p (op1_def_stmt_info))
{ scalar_shift_arg = false;
gimple *def = SSA_NAME_DEF_STMT (op1);
if (is_pattern_stmt_p (vinfo_for_stmt (def)))
scalar_shift_arg = false;
}
} }
else else
{ {
@ -10051,7 +10042,10 @@ get_same_sized_vectype (tree scalar_type, tree vector_type)
VINFO - the vect info of the loop or basic block that is being vectorized. VINFO - the vect info of the loop or basic block that is being vectorized.
OPERAND - operand in the loop or bb. OPERAND - operand in the loop or bb.
Output: Output:
DEF_STMT_OUT (optional) - the defining stmt in case OPERAND is an SSA_NAME. DEF_STMT_INFO_OUT (optional) - information about the defining stmt in
case OPERAND is an SSA_NAME that is defined in the vectorizable region
DEF_STMT_OUT (optional) - the defining stmt in case OPERAND is an SSA_NAME;
the definition could be anywhere in the function
DT - the type of definition DT - the type of definition
Returns whether a stmt with OPERAND can be vectorized. Returns whether a stmt with OPERAND can be vectorized.
@ -10064,8 +10058,10 @@ get_same_sized_vectype (tree scalar_type, tree vector_type)
bool bool
vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt, vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
gimple **def_stmt_out) stmt_vec_info *def_stmt_info_out, gimple **def_stmt_out)
{ {
if (def_stmt_info_out)
*def_stmt_info_out = NULL;
if (def_stmt_out) if (def_stmt_out)
*def_stmt_out = NULL; *def_stmt_out = NULL;
*dt = vect_unknown_def_type; *dt = vect_unknown_def_type;
@ -10113,6 +10109,8 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
*dt = vect_unknown_def_type; *dt = vect_unknown_def_type;
break; break;
} }
if (def_stmt_info_out)
*def_stmt_info_out = stmt_vinfo;
} }
if (def_stmt_out) if (def_stmt_out)
*def_stmt_out = def_stmt; *def_stmt_out = def_stmt;
@ -10175,14 +10173,18 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
bool bool
vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt, vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
tree *vectype, gimple **def_stmt_out) tree *vectype, stmt_vec_info *def_stmt_info_out,
gimple **def_stmt_out)
{ {
stmt_vec_info def_stmt_info;
gimple *def_stmt; gimple *def_stmt;
if (!vect_is_simple_use (operand, vinfo, dt, &def_stmt)) if (!vect_is_simple_use (operand, vinfo, dt, &def_stmt_info, &def_stmt))
return false; return false;
if (def_stmt_out) if (def_stmt_out)
*def_stmt_out = def_stmt; *def_stmt_out = def_stmt;
if (def_stmt_info_out)
*def_stmt_info_out = def_stmt_info;
/* Now get a vector type if the def is internal, otherwise supply /* Now get a vector type if the def is internal, otherwise supply
NULL_TREE and leave it up to the caller to figure out a proper NULL_TREE and leave it up to the caller to figure out a proper
@ -10193,8 +10195,7 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
|| *dt == vect_double_reduction_def || *dt == vect_double_reduction_def
|| *dt == vect_nested_cycle) || *dt == vect_nested_cycle)
{ {
stmt_vec_info stmt_info = vinfo_for_stmt (def_stmt); *vectype = STMT_VINFO_VECTYPE (def_stmt_info);
*vectype = STMT_VINFO_VECTYPE (stmt_info);
gcc_assert (*vectype != NULL_TREE); gcc_assert (*vectype != NULL_TREE);
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {

View File

@ -1532,9 +1532,10 @@ extern tree get_mask_type_for_scalar_type (tree);
extern tree get_same_sized_vectype (tree, tree); extern tree get_same_sized_vectype (tree, tree);
extern bool vect_get_loop_mask_type (loop_vec_info); extern bool vect_get_loop_mask_type (loop_vec_info);
extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *, extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
gimple ** = NULL); stmt_vec_info * = NULL, gimple ** = NULL);
extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *, extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
tree *, gimple ** = NULL); tree *, stmt_vec_info * = NULL,
gimple ** = NULL);
extern bool supportable_widening_operation (enum tree_code, gimple *, tree, extern bool supportable_widening_operation (enum tree_code, gimple *, tree,
tree, enum tree_code *, tree, enum tree_code *,
enum tree_code *, int *, enum tree_code *, int *,