From 0411210fddbd3ec27c8dc1183f40f662712a2232 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 31 Dec 2020 16:10:47 +0000 Subject: [PATCH] genmodes: Update GET_MODE_MASK when changing NUNITS [PR98214] The static GET_MODE_MASKs for SVE vectors are based on the static precisions, which in turn are based on 128-bit SVE. The precisions are later updated based on -msve-vector-bits (usually to become variable length), but the GET_MODE_MASK stayed the same. This caused combine to fold: (*_extract:DI (subreg:DI (reg:VNxMM R) 0) ...) to zero because the extracted bits appeared to be insignificant. gcc/ PR rtl-optimization/98214 * genmodes.c (emit_insn_modes_h): Emit a definition of CONST_MODE_MASK. (emit_mode_mask): Treat mode_mask_array as non-constant if adj_nunits. (emit_mode_adjustments): Update GET_MODE_MASK when updating GET_MODE_NUNITS. * machmode.h (mode_mask_array): Use CONST_MODE_MASK. --- gcc/genmodes.c | 22 ++++++++++++++++--- gcc/machmode.h | 3 ++- .../gcc.target/aarch64/sve/pr98214.c | 21 ++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr98214.c diff --git a/gcc/genmodes.c b/gcc/genmodes.c index 34b52fe41d6..d053eb3ebad 100644 --- a/gcc/genmodes.c +++ b/gcc/genmodes.c @@ -1324,6 +1324,7 @@ enum machine_mode\n{"); #endif printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const"); printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const"); + printf ("#define CONST_MODE_MASK%s\n", adj_nunits ? "" : " const"); emit_max_int (); for_all_modes (c, m) @@ -1561,8 +1562,8 @@ emit_mode_mask (void) int c; struct mode_data *m; - print_decl ("unsigned HOST_WIDE_INT", "mode_mask_array", - "NUM_MACHINE_MODES"); + print_maybe_const_decl ("%sunsigned HOST_WIDE_INT", "mode_mask_array", + "NUM_MACHINE_MODES", adj_nunits); puts ("\ #define MODE_MASK(m) \\\n\ ((m) >= HOST_BITS_PER_WIDE_INT) \\\n\ @@ -1719,6 +1720,20 @@ emit_mode_adjustments (void) struct mode_adjust *a; struct mode_data *m; + if (adj_nunits) + printf ("\n" + "void\n" + "adjust_mode_mask (machine_mode mode)\n" + "{\n" + " unsigned int precision;\n" + " if (GET_MODE_PRECISION (mode).is_constant (&precision)\n" + " && precision < HOST_BITS_PER_WIDE_INT)\n" + " mode_mask_array[mode] = (HOST_WIDE_INT_1U << precision) - 1;" + "\n" + " else\n" + " mode_mask_array[mode] = HOST_WIDE_INT_M1U;\n" + "}\n"); + puts ("\ \nvoid\ \ninit_adjust_machine_modes (void)\ @@ -1736,10 +1751,11 @@ emit_mode_adjustments (void) printf (" int old_factor = vector_element_size" " (mode_precision[E_%smode], mode_nunits[E_%smode]);\n", m->name, m->name); - printf (" mode_precision[E_%smode] = ps * old_factor;\n", m->name); + printf (" mode_precision[E_%smode] = ps * old_factor;\n", m->name); printf (" mode_size[E_%smode] = exact_div (mode_precision[E_%smode]," " BITS_PER_UNIT);\n", m->name, m->name); printf (" mode_nunits[E_%smode] = ps;\n", m->name); + printf (" adjust_mode_mask (E_%smode);\n", m->name); printf (" }\n"); } diff --git a/gcc/machmode.h b/gcc/machmode.h index bb3a5c6c27e..11247fc2006 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -712,7 +712,8 @@ extern CONST_MODE_FBIT unsigned char mode_fbit[NUM_MACHINE_MODES]; /* Get a bitmask containing 1 for all bits in a word that fit within mode MODE. */ -extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES]; +extern CONST_MODE_MASK unsigned HOST_WIDE_INT + mode_mask_array[NUM_MACHINE_MODES]; #define GET_MODE_MASK(MODE) mode_mask_array[MODE] diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr98214.c b/gcc/testsuite/gcc.target/aarch64/sve/pr98214.c new file mode 100644 index 00000000000..2de9625e98d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr98214.c @@ -0,0 +1,21 @@ +/* { dg-options "-O3 -msve-vector-bits=512" } */ + +long c; +int a; +int e[14]; +short b[14]; +void d(long *f, long h) { *f ^= h + *f; } +void this_test_has_completed_successfully (); +int main() { + e[2] = 1; + for (int g = 0; g < 13; g++) + a = b[g] = e[g]; + d(&c, a); + for (int g = 0; g < 4; g++) + d(&c, b[2]); + if (c != 15) + __builtin_abort(); + this_test_has_completed_successfully (); +} + +/* { dg-final { scan-assembler {this_test_has_completed_successfully} } } */ -- 2.30.2