tree-optimization/97706 - handle PHIs in pattern recog mask precison

This adds handling of PHIs to mask precision compute which is
eventually needed to detect a bool pattern when the def chain
contains such a PHI node.

2020-11-06  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/97706
	* tree-vect-patterns.c (possible_vector_mask_operation_p):
	PHIs are possible mask operations.
	(vect_determine_mask_precision): Handle PHIs.
	(vect_determine_precisions): Walk PHIs in BB analysis.

	* gcc.dg/vect/bb-slp-pr97706.c: New testcase.
This commit is contained in:
Richard Biener 2020-11-05 12:34:42 +01:00
parent 1db815f4f3
commit 22175d0dc6
2 changed files with 137 additions and 37 deletions

View File

@ -0,0 +1,61 @@
/* { dg-do compile } */
_Bool arr[16];
void bar();
void foo(int n, char *p)
{
_Bool b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;
do
{
b0 = p[0] != 0;
b1 = p[1] != 0;
b2 = p[2] != 0;
b3 = p[3] != 0;
b4 = p[4] != 0;
b5 = p[5] != 0;
b6 = p[6] != 0;
b7 = p[7] != 0;
b8 = p[8] != 0;
b9 = p[9] != 0;
b10 = p[10] != 0;
b11 = p[11] != 0;
b12 = p[12] != 0;
b13 = p[13] != 0;
b14 = p[14] != 0;
b15 = p[15] != 0;
arr[0] = b0;
arr[1] = b1;
arr[2] = b2;
arr[3] = b3;
arr[4] = b4;
arr[5] = b5;
arr[6] = b6;
arr[7] = b7;
arr[8] = b8;
arr[9] = b9;
arr[10] = b10;
arr[11] = b11;
arr[12] = b12;
arr[13] = b13;
arr[14] = b14;
arr[15] = b15;
bar ();
}
while (--n);
arr[0] = b0;
arr[1] = b1;
arr[2] = b2;
arr[3] = b3;
arr[4] = b4;
arr[5] = b5;
arr[6] = b6;
arr[7] = b7;
arr[8] = b8;
arr[9] = b9;
arr[10] = b10;
arr[11] = b11;
arr[12] = b12;
arr[13] = b13;
arr[14] = b14;
arr[15] = b15;
}

View File

@ -5007,6 +5007,8 @@ possible_vector_mask_operation_p (stmt_vec_info stmt_info)
return TREE_CODE_CLASS (rhs_code) == tcc_comparison;
}
}
else if (is_a <gphi *> (stmt_info->stmt))
return true;
return false;
}
@ -5049,41 +5051,63 @@ vect_determine_mask_precision (vec_info *vinfo, stmt_vec_info stmt_info)
The number of operations are equal, but M16 would have given
a shorter dependency chain and allowed more ILP. */
unsigned int precision = ~0U;
gassign *assign = as_a <gassign *> (stmt_info->stmt);
unsigned int nops = gimple_num_ops (assign);
for (unsigned int i = 1; i < nops; ++i)
if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
{
tree rhs = gimple_op (assign, i);
if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs)))
continue;
stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
if (!def_stmt_info)
/* Don't let external or constant operands influence the choice.
We can convert them to whichever vector type we pick. */
continue;
if (def_stmt_info->mask_precision)
unsigned int nops = gimple_num_ops (assign);
for (unsigned int i = 1; i < nops; ++i)
{
if (precision > def_stmt_info->mask_precision)
precision = def_stmt_info->mask_precision;
tree rhs = gimple_op (assign, i);
if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs)))
continue;
stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
if (!def_stmt_info)
/* Don't let external or constant operands influence the choice.
We can convert them to whichever vector type we pick. */
continue;
if (def_stmt_info->mask_precision)
{
if (precision > def_stmt_info->mask_precision)
precision = def_stmt_info->mask_precision;
}
}
/* If the statement compares two values that shouldn't use vector masks,
try comparing the values as normal scalars instead. */
tree_code rhs_code = gimple_assign_rhs_code (assign);
if (precision == ~0U
&& TREE_CODE_CLASS (rhs_code) == tcc_comparison)
{
tree rhs1_type = TREE_TYPE (gimple_assign_rhs1 (assign));
scalar_mode mode;
tree vectype, mask_type;
if (is_a <scalar_mode> (TYPE_MODE (rhs1_type), &mode)
&& (vectype = get_vectype_for_scalar_type (vinfo, rhs1_type))
&& (mask_type = get_mask_type_for_scalar_type (vinfo, rhs1_type))
&& expand_vec_cmp_expr_p (vectype, mask_type, rhs_code))
precision = GET_MODE_BITSIZE (mode);
}
}
/* If the statement compares two values that shouldn't use vector masks,
try comparing the values as normal scalars instead. */
tree_code rhs_code = gimple_assign_rhs_code (assign);
if (precision == ~0U
&& TREE_CODE_CLASS (rhs_code) == tcc_comparison)
else
{
tree rhs1_type = TREE_TYPE (gimple_assign_rhs1 (assign));
scalar_mode mode;
tree vectype, mask_type;
if (is_a <scalar_mode> (TYPE_MODE (rhs1_type), &mode)
&& (vectype = get_vectype_for_scalar_type (vinfo, rhs1_type))
&& (mask_type = get_mask_type_for_scalar_type (vinfo, rhs1_type))
&& expand_vec_cmp_expr_p (vectype, mask_type, rhs_code))
precision = GET_MODE_BITSIZE (mode);
gphi *phi = as_a <gphi *> (stmt_info->stmt);
for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
{
tree rhs = gimple_phi_arg_def (phi, i);
stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
if (!def_stmt_info)
/* Don't let external or constant operands influence the choice.
We can convert them to whichever vector type we pick. */
continue;
if (def_stmt_info->mask_precision)
{
if (precision > def_stmt_info->mask_precision)
precision = def_stmt_info->mask_precision;
}
}
}
if (dump_enabled_p ())
@ -5164,15 +5188,30 @@ vect_determine_precisions (vec_info *vinfo)
if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
vect_determine_mask_precision (vinfo, stmt_info);
}
for (auto gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi.phi ());
if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
vect_determine_mask_precision (vinfo, stmt_info);
}
}
for (int i = bb_vinfo->bbs.length () - 1; i != -1; --i)
for (gimple_stmt_iterator gsi = gsi_last_bb (bb_vinfo->bbs[i]);
!gsi_end_p (gsi); gsi_prev (&gsi))
{
stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
vect_determine_stmt_precisions (vinfo, stmt_info);
}
{
for (gimple_stmt_iterator gsi = gsi_last_bb (bb_vinfo->bbs[i]);
!gsi_end_p (gsi); gsi_prev (&gsi))
{
stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
vect_determine_stmt_precisions (vinfo, stmt_info);
}
for (auto gsi = gsi_start_phis (bb_vinfo->bbs[i]);
!gsi_end_p (gsi); gsi_next (&gsi))
{
stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi.phi ());
if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
vect_determine_stmt_precisions (vinfo, stmt_info);
}
}
}
}