diff mbox series

[pushed] genmodes: Update GET_MODE_MASK when changing NUNITS [PR98214]

Message ID mpt8s9ej6kx.fsf@arm.com
State New
Headers show
Series [pushed] genmodes: Update GET_MODE_MASK when changing NUNITS [PR98214] | expand

Commit Message

Richard Sandiford Dec. 31, 2020, 4:14 p.m. UTC
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.

Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu.
Pushed to trunk so far, will push to GCC 10 branch soon(ish).

Richard


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 mbox series

Patch

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} } } */