aarch64: Fix folding of degenerate svwhilele case [PR117045]
The svwhilele folder mishandled the degenerate case in which the second argument is the maximum integer. In that case, the result is all-true regardless of the first parameter: If the second scalar operand is equal to the maximum signed integer value then a condition which includes an equality test can never fail and the result will be an all-true predicate. This is because the conceptual "increment the first operand by 1 after each element" is done modulo the range of the operand. The GCC code was instead treating it as infinite precision. whilele_5.c even had a test for the incorrect behaviour. The easiest fix seemed to be to handle that case specially before doing constant folding. This also copes with variable first operands. gcc/ PR target/116999 PR target/117045 * config/aarch64/aarch64-sve-builtins-base.cc (svwhilelx_impl::fold): Check for WHILELTs of the minimum value and WHILELEs of the maximum value. Fold them to all-false and all-true respectively. gcc/testsuite/ PR target/116999 PR target/117045 * gcc.target/aarch64/sve/acle/general/whilele_5.c: Fix bogus expected result. * gcc.target/aarch64/sve/acle/general/whilele_11.c: New test. * gcc.target/aarch64/sve/acle/general/whilele_12.c: Likewise.
This commit is contained in:
parent
9f549d216c
commit
50e7c51b0a
4 changed files with 76 additions and 2 deletions
|
@ -2945,7 +2945,9 @@ public:
|
|||
: while_comparison (unspec_for_sint, unspec_for_uint), m_eq_p (eq_p)
|
||||
{}
|
||||
|
||||
/* Try to fold a call by treating its arguments as constants of type T. */
|
||||
/* Try to fold a call by treating its arguments as constants of type T.
|
||||
We have already filtered out the degenerate cases of X .LT. MIN
|
||||
and X .LE. MAX. */
|
||||
template<typename T>
|
||||
gimple *
|
||||
fold_type (gimple_folder &f) const
|
||||
|
@ -3001,6 +3003,13 @@ public:
|
|||
if (f.vectors_per_tuple () > 1)
|
||||
return nullptr;
|
||||
|
||||
/* Filter out cases where the condition is always true or always false. */
|
||||
tree arg1 = gimple_call_arg (f.call, 1);
|
||||
if (!m_eq_p && operand_equal_p (arg1, TYPE_MIN_VALUE (TREE_TYPE (arg1))))
|
||||
return f.fold_to_pfalse ();
|
||||
if (m_eq_p && operand_equal_p (arg1, TYPE_MAX_VALUE (TREE_TYPE (arg1))))
|
||||
return f.fold_to_ptrue ();
|
||||
|
||||
if (f.type_suffix (1).unsigned_p)
|
||||
return fold_type<poly_uint64> (f);
|
||||
else
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
#include <arm_sve.h>
|
||||
#include <limits.h>
|
||||
|
||||
svbool_t
|
||||
f1 (volatile int32_t *ptr)
|
||||
{
|
||||
return svwhilelt_b8_s32 (*ptr, INT32_MIN);
|
||||
}
|
||||
|
||||
svbool_t
|
||||
f2 (volatile uint32_t *ptr)
|
||||
{
|
||||
return svwhilelt_b16_u32 (*ptr, 0);
|
||||
}
|
||||
|
||||
svbool_t
|
||||
f3 (volatile int64_t *ptr)
|
||||
{
|
||||
return svwhilelt_b32_s64 (*ptr, INT64_MIN);
|
||||
}
|
||||
|
||||
svbool_t
|
||||
f4 (volatile uint64_t *ptr)
|
||||
{
|
||||
return svwhilelt_b64_u64 (*ptr, 0);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times {\tpfalse\tp[0-9]+\.b\n} 4 } } */
|
|
@ -0,0 +1,34 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
#include <arm_sve.h>
|
||||
#include <limits.h>
|
||||
|
||||
svbool_t
|
||||
f1 (volatile int32_t *ptr)
|
||||
{
|
||||
return svwhilele_b8_s32 (*ptr, INT32_MAX);
|
||||
}
|
||||
|
||||
svbool_t
|
||||
f2 (volatile uint32_t *ptr)
|
||||
{
|
||||
return svwhilele_b16_u32 (*ptr, UINT32_MAX);
|
||||
}
|
||||
|
||||
svbool_t
|
||||
f3 (volatile int64_t *ptr)
|
||||
{
|
||||
return svwhilele_b32_s64 (*ptr, INT64_MAX);
|
||||
}
|
||||
|
||||
svbool_t
|
||||
f4 (volatile uint64_t *ptr)
|
||||
{
|
||||
return svwhilele_b64_u64 (*ptr, UINT64_MAX);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-9]+\.b(?:, all)\n} } } */
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-9]+\.h(?:, all)\n} } } */
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-9]+\.s(?:, all)\n} } } */
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-9]+\.d(?:, all)\n} } } */
|
|
@ -28,7 +28,7 @@ test3 (svbool_t *ptr)
|
|||
*ptr = svwhilele_b16_s32 (0x7ffffffb, 0x7fffffff);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-9]+\.h, vl5\n} } } */
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-9]+\.h(?:, all)\n} } } */
|
||||
|
||||
void
|
||||
test4 (svbool_t *ptr)
|
||||
|
|
Loading…
Add table
Reference in a new issue