aboutsummaryrefslogtreecommitdiff
path: root/gcc/genmodes.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2020-12-31 16:10:47 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2020-12-31 16:10:47 +0000
commit0411210fddbd3ec27c8dc1183f40f662712a2232 (patch)
tree8e8148d489ca4378607eb44f5cc7f1da15d9343f /gcc/genmodes.c
parentd2eb616a0f7bea78164912aa438c29fe1ef5774a (diff)
downloadgcc-0411210fddbd3ec27c8dc1183f40f662712a2232.zip
gcc-0411210fddbd3ec27c8dc1183f40f662712a2232.tar.gz
gcc-0411210fddbd3ec27c8dc1183f40f662712a2232.tar.bz2
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.
Diffstat (limited to 'gcc/genmodes.c')
-rw-r--r--gcc/genmodes.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 34b52fe..d053eb3 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");
}