Check for matching CONST_VECTOR encodings [PR99929]
PR99929 is one of those “how did we get away with this for so long” bugs: the equality routines weren't checking whether two variable-length CONST_VECTORs had the same encoding. This meant that: { 1, 0, 0, 0, 0, 0, ... } would appear to be equal to: { 1, 0, 1, 0, 1, 0, ... } since both are represented using the elements { 1, 0 }. gcc/ PR rtl-optimization/99929 * rtl.h (same_vector_encodings_p): New function. * cse.c (exp_equiv_p): Check that CONST_VECTORs have the same encoding. * cselib.c (rtx_equal_for_cselib_1): Likewise. * jump.c (rtx_renumbered_equal_p): Likewise. * lra-constraints.c (operands_match_p): Likewise. * reload.c (operands_match_p): Likewise. * rtl.c (rtx_equal_p_cb, rtx_equal_p): Likewise. gcc/testsuite/ * gcc.target/aarch64/sve/pr99929_1.c: New file. * gcc.target/aarch64/sve/pr99929_2.c: Likewise.
This commit is contained in:
parent
1fce5932a3
commit
a87d3f964d
9 changed files with 73 additions and 0 deletions
|
@ -2637,6 +2637,11 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
|
|||
CASE_CONST_UNIQUE:
|
||||
return x == y;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
return label_ref_label (x) == label_ref_label (y);
|
||||
|
||||
|
|
|
@ -1048,6 +1048,11 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, machine_mode memmode, int depth)
|
|||
case DEBUG_EXPR:
|
||||
return 0;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case DEBUG_IMPLICIT_PTR:
|
||||
return DEBUG_IMPLICIT_PTR_DECL (x)
|
||||
== DEBUG_IMPLICIT_PTR_DECL (y);
|
||||
|
|
|
@ -1777,6 +1777,11 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
|
|||
CASE_CONST_UNIQUE:
|
||||
return 0;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
/* We can't assume nonlocal labels have their following insns yet. */
|
||||
if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
|
||||
|
|
|
@ -834,6 +834,11 @@ operands_match_p (rtx x, rtx y, int y_hard_regno)
|
|||
CASE_CONST_UNIQUE:
|
||||
return false;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
return label_ref_label (x) == label_ref_label (y);
|
||||
case SYMBOL_REF:
|
||||
|
|
|
@ -2310,6 +2310,11 @@ operands_match_p (rtx x, rtx y)
|
|||
CASE_CONST_UNIQUE:
|
||||
return 0;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
return label_ref_label (x) == label_ref_label (y);
|
||||
case SYMBOL_REF:
|
||||
|
|
10
gcc/rtl.c
10
gcc/rtl.c
|
@ -466,6 +466,11 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
|
|||
CASE_CONST_UNIQUE:
|
||||
return 0;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case DEBUG_IMPLICIT_PTR:
|
||||
return DEBUG_IMPLICIT_PTR_DECL (x)
|
||||
== DEBUG_IMPLICIT_PTR_DECL (y);
|
||||
|
@ -608,6 +613,11 @@ rtx_equal_p (const_rtx x, const_rtx y)
|
|||
CASE_CONST_UNIQUE:
|
||||
return 0;
|
||||
|
||||
case CONST_VECTOR:
|
||||
if (!same_vector_encodings_p (x, y))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case DEBUG_IMPLICIT_PTR:
|
||||
return DEBUG_IMPLICIT_PTR_DECL (x)
|
||||
== DEBUG_IMPLICIT_PTR_DECL (y);
|
||||
|
|
17
gcc/rtl.h
17
gcc/rtl.h
|
@ -3087,6 +3087,23 @@ vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
|
|||
return const_vec_series_p (x, base_out, step_out);
|
||||
}
|
||||
|
||||
/* Return true if CONST_VECTORs X and Y, which are known to have the same mode,
|
||||
also have the same encoding. This means that they are equal whenever their
|
||||
operands are equal. */
|
||||
|
||||
inline bool
|
||||
same_vector_encodings_p (const_rtx x, const_rtx y)
|
||||
{
|
||||
/* Don't be fussy about the encoding of constant-length vectors,
|
||||
since XVECEXP (X, 0) and XVECEXP (Y, 0) list all the elements anyway. */
|
||||
if (poly_uint64 (CONST_VECTOR_NUNITS (x)).is_constant ())
|
||||
return true;
|
||||
|
||||
return (CONST_VECTOR_NPATTERNS (x) == CONST_VECTOR_NPATTERNS (y)
|
||||
&& (CONST_VECTOR_NELTS_PER_PATTERN (x)
|
||||
== CONST_VECTOR_NELTS_PER_PATTERN (y)));
|
||||
}
|
||||
|
||||
/* Return the unpromoted (outer) mode of SUBREG_PROMOTED_VAR_P subreg X. */
|
||||
|
||||
inline scalar_int_mode
|
||||
|
|
16
gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c
Normal file
16
gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* { dg-do run { target aarch64_sve_hw } } */
|
||||
/* { dg-options "-O2 -ftree-vectorize" } */
|
||||
|
||||
#include <arm_sve.h>
|
||||
|
||||
static void e(short *g, short p2) { *g ^= p2; }
|
||||
static short m[23];
|
||||
int main() {
|
||||
for (unsigned i = 0; i < 23; ++i)
|
||||
m[i] = 4;
|
||||
if (svaddv(svptrue_pat_b32(SV_VL1), svdup_u32(1)) != 1)
|
||||
__builtin_abort();
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
e(m, m[i]);
|
||||
return 0;
|
||||
}
|
5
gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c
Normal file
5
gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* { dg-options "-O2 -ftree-vectorize" } */
|
||||
|
||||
#include "pr99929_1.c"
|
||||
|
||||
/* { dg-final { scan-assembler {\tptrue\tp[0-7].[bhsd], vl1\n} } } */
|
Loading…
Add table
Reference in a new issue