Jeff Law <l...@redhat.com> writes: > On 05/07/2015 05:37 AM, Richard Sandiford wrote: >> One problem with the automatically-generated gen_rtx_FOO () macros >> is that they always have a mode parameter, even for codes like SET >> where the mode should always be VOIDmode. This inevitably leads to >> cases where a caller accidentally passes something other than VOIDmode. >> E.g. when expanding an SImode move, the temptation is to make everything >> SImode, even the SETs. This in turn can cause two instructions to appear >> different simply because their SETs have different modes, even though the >> SET_DEST and SET_SRC are identical. >> >> E.g. for gcc/testsuite/g++.dg/torture/pr34651.C on lm32-elf we have >> the following before jump2: >> >> (jump_insn 42 191 43 5 (set (pc) >> (if_then_else (eq:SI (reg:SI 13 r13 [orig:43 inHotKey$4+-3 ] [43]) >> (const_int 0 [0])) >> (label_ref 53) >> (pc))) gcc/testsuite/g++.dg/torture/pr34651.C:22 22 {*beq} >> (expr_list:REG_DEAD (reg:SI 13 r13 [orig:43 inHotKey$4+-3 ] [43]) >> (int_list:REG_BR_PROB 5000 (nil))) >> -> 53) >> (note 43 42 48 6 [bb 6] NOTE_INSN_BASIC_BLOCK) >> (insn 48 43 47 6 (set (reg:SI 2 r2) >> (mem/u/c:SI (reg:SI 1 r1) [4 S4 A32])) >> gcc/testsuite/g++.dg/torture/pr34651.C:22 7 {movsi_insn} >> (expr_list:REG_DEAD (reg:SI 1 r1) >> (nil))) >> [...] >> (code_label 53 169 54 7 6 "" [1 uses]) >> (note 54 53 12 7 [bb 7] NOTE_INSN_BASIC_BLOCK) >> (insn 12 54 57 7 (set:SI (reg/f:SI 2 r2 [orig:46 D.2050 ] [46]) >> (mem/u/c:SI (reg:SI 1 r1) [4 S4 A32])) >> gcc/testsuite/g++.dg/torture/pr34651.C:22 7 {movsi_insn} >> (expr_list:REG_DEAD (reg:SI 1 r1) >> (expr_list:REG_EQUAL (symbol_ref/f:SI ("*.LC3") [flags 0x2] >> <var_decl # *.LC3>) >> (nil)))) >> >> where insns 12 and 48 are identical except for the :SI on the SET. >> This difference prevents us from merging the heads of the two blocks; >> after removing it we replace the two loads with a single load before >> the branch. >> >> This patch removes the mode argument from gen_rtx_SET and updates >> all callers. I used a script to (try to) make sure that all callers >> really had been caught. I also built one target per CPU just in case. >> There were some changes in gcc.dg, g++.dg and gcc.c-torture assembly >> code for c6x-elf, lm32-elf and v850-elf, but all of them seemed to be >> code improvements from removing duplicated instructions. (Other ports >> also passed spurious modes but apparently not in a way that affects >> the tests I'd tried.) Also tested on x86_64-linux-gnu. OK to install? >> >> BTW, I've split the patch up into two, the last bit being a mechanical >> removal of modes. (I did it by hand though to try to keep things >> properly formatted.) >> >> Thanks, >> Richard >> >> >> gcc/ >> * rtl.h (always_void_p): New function. >> * gengenrtl.c (always_void_p(: Likewise. > Typo in the ChangeLog. > > non-mechanical part didn't seem to be attached. I don't expect any > problems there, but a quick looksie seems appropriate.
Bah. Sorry about that. It's unfortunate that we have two copies of the test -- one on codes and one on strings -- but that's how everything else in gengenrtl.c is done. Maybe a later clean-up. Index: gcc/genemit.c =================================================================== --- gcc/genemit.c 2015-05-07 07:59:47.890577327 +0100 +++ gcc/genemit.c 2015-05-07 07:59:47.874577523 +0100 @@ -94,6 +94,7 @@ gen_exp (rtx x, enum rtx_code subroutine int i; int len; const char *fmt; + const char *sep = ""; if (x == 0) { @@ -215,7 +216,12 @@ gen_exp (rtx x, enum rtx_code subroutine printf ("gen_rtx_"); print_code (code); - printf (" (%smode", GET_MODE_NAME (GET_MODE (x))); + printf (" ("); + if (!always_void_p (code)) + { + printf ("%smode", GET_MODE_NAME (GET_MODE (x))); + sep = ",\n\t"; + } fmt = GET_RTX_FORMAT (code); len = GET_RTX_LENGTH (code); @@ -223,7 +229,7 @@ gen_exp (rtx x, enum rtx_code subroutine { if (fmt[i] == '0') break; - printf (",\n\t"); + fputs (sep, stdout); switch (fmt[i]) { case 'e': case 'u': @@ -254,6 +260,7 @@ gen_exp (rtx x, enum rtx_code subroutine default: gcc_unreachable (); } + sep = ",\n\t"; } printf (")"); } Index: gcc/gengenrtl.c =================================================================== --- gcc/gengenrtl.c 2015-05-07 07:59:47.890577327 +0100 +++ gcc/gengenrtl.c 2015-05-07 08:12:24.281310491 +0100 @@ -116,6 +116,14 @@ special_format (const char *fmt) || strchr (fmt, 'n') != 0); } +/* Return true if CODE always has VOIDmode. */ + +static inline bool +always_void_p (int idx) +{ + return strcmp (defs[idx].enumname, "SET") == 0; +} + /* Return nonzero if the RTL code given by index IDX is one that we should generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO is a wrapper in emit-rtl.c). */ @@ -181,6 +189,7 @@ find_formats (void) genmacro (int idx) { const char *p; + const char *sep = ""; int i; /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to @@ -190,15 +199,25 @@ genmacro (int idx) /* Don't define a macro for this code. */ return; - printf ("#define gen_rtx_%s%s(MODE", + bool has_mode_p = !always_void_p (idx); + printf ("#define gen_rtx_%s%s(", special_rtx (idx) ? "raw_" : "", defs[idx].enumname); + if (has_mode_p) + { + printf ("MODE"); + sep = ", "; + } for (p = defs[idx].format, i = 0; *p != 0; p++) if (*p != '0') - printf (", ARG%d", i++); - - printf (") \\\n gen_rtx_fmt_%s (%s, (MODE)", - defs[idx].format, defs[idx].enumname); + { + printf ("%sARG%d", sep, i++); + sep = ", "; + } + + printf (") \\\n gen_rtx_fmt_%s (%s, %s", + defs[idx].format, defs[idx].enumname, + has_mode_p ? "(MODE)" : "VOIDmode"); for (p = defs[idx].format, i = 0; *p != 0; p++) if (*p != '0') Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2015-05-07 07:59:47.890577327 +0100 +++ gcc/rtl.h 2015-05-07 08:11:56.405652046 +0100 @@ -1787,6 +1787,14 @@ #define COSTS_N_INSNS(N) ((N) * 4) not to use an rtx with this cost under any circumstances. */ #define MAX_COST INT_MAX +/* Return true if CODE always has VOIDmode. */ + +static inline bool +always_void_p (enum rtx_code code) +{ + return code == SET; +} + /* A structure to hold all available cost information about an rtl expression. */ struct full_rtx_costs @@ -3597,5 +3605,4 @@ #define fatal_insn_not_found(insn) \ /* reginfo.c */ extern tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER]; - #endif /* ! GCC_RTL_H */