vect: Fix wrong check in vect_recog_mulhs_pattern [PR101596]
As PR101596 showed, vect_recog_mulhs_pattern uses target_precision to check the scale_term is expected or not, it could be wrong when the precision of the actual used new_type larger than target_precision as shown by the example. This patch is to use precision of new_type instead of target_precision for the scale_term matching check. Bootstrapped & regtested on powerpc64le-linux-gnu P10, powerpc64-linux-gnu P8, x86_64-redhat-linux and aarch64-linux-gnu. gcc/ChangeLog: PR tree-optimization/101596 * tree-vect-patterns.c (vect_recog_mulhs_pattern): Fix wrong check by using new_type's precision instead. gcc/testsuite/ChangeLog: PR tree-optimization/101596 * gcc.target/powerpc/pr101596-1.c: New test. * gcc.target/powerpc/pr101596-2.c: Likewise. * gcc.target/powerpc/pr101596-3.c: Likewise.
This commit is contained in:
parent
872da9a6f6
commit
89b3c97eed
30
gcc/testsuite/gcc.target/powerpc/pr101596-1.c
Normal file
30
gcc/testsuite/gcc.target/powerpc/pr101596-1.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* { dg-require-effective-target power10_ok } */
|
||||
/* { dg-options "-mdejagnu-cpu=power10 -O2 -ftree-vectorize -fno-vect-cost-model -fdump-tree-vect-details" } */
|
||||
|
||||
/* Check vect_recog_mulhs_pattern can't be detected with shift count 48. */
|
||||
|
||||
#define N 128
|
||||
|
||||
typedef signed long long sLL;
|
||||
typedef unsigned long long uLL;
|
||||
|
||||
signed int si_a[N], si_b[N];
|
||||
unsigned int ui_a[N], ui_b[N];
|
||||
signed short sh_c[N];
|
||||
unsigned short uh_c[N];
|
||||
|
||||
void
|
||||
test1 ()
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
sh_c[i] = ((sLL) si_a[i] * (sLL) si_b[i]) >> 48;
|
||||
}
|
||||
|
||||
void
|
||||
test2 ()
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
uh_c[i] = ((uLL) ui_a[i] * (uLL) ui_b[i]) >> 48;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "vect_recog_mulhs_pattern: detected" "vect" } } */
|
30
gcc/testsuite/gcc.target/powerpc/pr101596-2.c
Normal file
30
gcc/testsuite/gcc.target/powerpc/pr101596-2.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* { dg-require-effective-target power10_ok } */
|
||||
/* { dg-options "-mdejagnu-cpu=power10 -O2 -ftree-vectorize -fno-vect-cost-model -fdump-tree-vect-details" } */
|
||||
|
||||
/* Check vect_recog_mulhs_pattern can be detected with shift count 32. */
|
||||
|
||||
#define N 128
|
||||
|
||||
typedef signed long long sLL;
|
||||
typedef unsigned long long uLL;
|
||||
|
||||
signed int si_a[N], si_b[N];
|
||||
unsigned int ui_a[N], ui_b[N];
|
||||
signed short sh_c[N];
|
||||
unsigned short uh_c[N];
|
||||
|
||||
void
|
||||
test1 ()
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
sh_c[i] = ((sLL) si_a[i] * (sLL) si_b[i]) >> 32;
|
||||
}
|
||||
|
||||
void
|
||||
test2 ()
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
uh_c[i] = ((uLL) ui_a[i] * (uLL) ui_b[i]) >> 32;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "vect_recog_mulhs_pattern: detected" 2 "vect" } } */
|
58
gcc/testsuite/gcc.target/powerpc/pr101596-3.c
Normal file
58
gcc/testsuite/gcc.target/powerpc/pr101596-3.c
Normal file
@ -0,0 +1,58 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target power10_hw } */
|
||||
/* { dg-options "-mdejagnu-cpu=power10 -O2 -ftree-vectorize -fno-vect-cost-model" } */
|
||||
|
||||
/* Verify the execution goes well with shift count either 32 or 48. */
|
||||
|
||||
#define N 128
|
||||
|
||||
typedef signed int si;
|
||||
typedef signed short sh;
|
||||
typedef signed long long sll;
|
||||
typedef unsigned int ui;
|
||||
typedef unsigned short uh;
|
||||
typedef unsigned long long ull;
|
||||
|
||||
si si_a[N], si_b[N];
|
||||
ui ui_a[N], ui_b[N];
|
||||
sh sh_c[N];
|
||||
uh uh_c[N];
|
||||
|
||||
#define TEST(NTYPE, TYPE, WTYPE, CNT) \
|
||||
void __attribute__ ((noipa)) test_##TYPE##CNT () \
|
||||
{ \
|
||||
for (int i = 0; i < N; i++) \
|
||||
NTYPE##_c[i] = ((WTYPE) TYPE##_a[i] * (WTYPE) TYPE##_b[i]) >> CNT; \
|
||||
} \
|
||||
\
|
||||
void __attribute__ ((noipa, optimize ("O1"))) check_##TYPE##CNT () \
|
||||
{ \
|
||||
test_##TYPE##CNT (); \
|
||||
for (int i = 0; i < N; i++) \
|
||||
{ \
|
||||
NTYPE exp = ((WTYPE) TYPE##_a[i] * (WTYPE) TYPE##_b[i]) >> CNT; \
|
||||
if (NTYPE##_c[i] != exp) \
|
||||
__builtin_abort (); \
|
||||
} \
|
||||
}
|
||||
|
||||
TEST (sh, si, sll, 32)
|
||||
TEST (sh, si, sll, 48)
|
||||
TEST (uh, ui, ull, 32)
|
||||
TEST (uh, ui, ull, 48)
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
ui_a[i] = si_a[i] = 0x12345678ULL + 0x1000ULL * (i * 3 - 1);
|
||||
ui_b[i] = si_b[i] = 0x87654321ULL - 0x500000ULL * (i * 5 + 1);
|
||||
}
|
||||
|
||||
check_si32 ();
|
||||
check_si48 ();
|
||||
check_ui32 ();
|
||||
check_ui48 ();
|
||||
}
|
@ -1986,7 +1986,7 @@ vect_recog_mulhs_pattern (vec_info *vinfo,
|
||||
|
||||
stmt_vec_info mulh_stmt_info;
|
||||
tree scale_term;
|
||||
internal_fn ifn;
|
||||
bool rounding_p = false;
|
||||
|
||||
/* Check for the presence of the rounding term. */
|
||||
if (gimple_assign_rhs_code (rshift_input_stmt) == PLUS_EXPR)
|
||||
@ -2035,37 +2035,18 @@ vect_recog_mulhs_pattern (vec_info *vinfo,
|
||||
|
||||
/* Get the scaling term. */
|
||||
scale_term = gimple_assign_rhs2 (plus_input_stmt);
|
||||
/* Check that the scaling factor is correct. */
|
||||
if (TREE_CODE (scale_term) != INTEGER_CST)
|
||||
return NULL;
|
||||
|
||||
/* Check pattern 2). */
|
||||
if (wi::to_widest (scale_term) + target_precision + 2
|
||||
!= TYPE_PRECISION (lhs_type))
|
||||
return NULL;
|
||||
|
||||
ifn = IFN_MULHRS;
|
||||
rounding_p = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mulh_stmt_info = rshift_input_stmt_info;
|
||||
scale_term = gimple_assign_rhs2 (last_stmt);
|
||||
/* Check that the scaling factor is correct. */
|
||||
if (TREE_CODE (scale_term) != INTEGER_CST)
|
||||
return NULL;
|
||||
|
||||
/* Check for pattern 1). */
|
||||
if (wi::to_widest (scale_term) + target_precision + 1
|
||||
== TYPE_PRECISION (lhs_type))
|
||||
ifn = IFN_MULHS;
|
||||
/* Check for pattern 3). */
|
||||
else if (wi::to_widest (scale_term) + target_precision
|
||||
== TYPE_PRECISION (lhs_type))
|
||||
ifn = IFN_MULH;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check that the scaling factor is constant. */
|
||||
if (TREE_CODE (scale_term) != INTEGER_CST)
|
||||
return NULL;
|
||||
|
||||
/* Check whether the scaling input term can be seen as two widened
|
||||
inputs multiplied together. */
|
||||
vect_unpromoted_value unprom_mult[2];
|
||||
@ -2076,13 +2057,41 @@ vect_recog_mulhs_pattern (vec_info *vinfo,
|
||||
if (nops != 2)
|
||||
return NULL;
|
||||
|
||||
vect_pattern_detected ("vect_recog_mulhs_pattern", last_stmt);
|
||||
|
||||
/* Adjust output precision. */
|
||||
if (TYPE_PRECISION (new_type) < target_precision)
|
||||
new_type = build_nonstandard_integer_type
|
||||
(target_precision, TYPE_UNSIGNED (new_type));
|
||||
|
||||
unsigned mult_precision = TYPE_PRECISION (new_type);
|
||||
internal_fn ifn;
|
||||
/* Check that the scaling factor is expected. Instead of
|
||||
target_precision, we should use the one that we actually
|
||||
use for internal function. */
|
||||
if (rounding_p)
|
||||
{
|
||||
/* Check pattern 2). */
|
||||
if (wi::to_widest (scale_term) + mult_precision + 2
|
||||
!= TYPE_PRECISION (lhs_type))
|
||||
return NULL;
|
||||
|
||||
ifn = IFN_MULHRS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check for pattern 1). */
|
||||
if (wi::to_widest (scale_term) + mult_precision + 1
|
||||
== TYPE_PRECISION (lhs_type))
|
||||
ifn = IFN_MULHS;
|
||||
/* Check for pattern 3). */
|
||||
else if (wi::to_widest (scale_term) + mult_precision
|
||||
== TYPE_PRECISION (lhs_type))
|
||||
ifn = IFN_MULH;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vect_pattern_detected ("vect_recog_mulhs_pattern", last_stmt);
|
||||
|
||||
/* Check for target support. */
|
||||
tree new_vectype = get_vectype_for_scalar_type (vinfo, new_type);
|
||||
if (!new_vectype
|
||||
|
Loading…
Reference in New Issue
Block a user