[backport from gcc-4.8/trunk r189366 ] From: Steven Bosscher Date: Sun, 8 Jul 2012 21:44:26 +0200 Subject: [patch] Rebase insn data to make CODE_FOR_nothing == 0, revert r161809 List-Archive: Hello, A lot of optab_handler checks are against CODE_FOR_nothing, which is currently a target dependent number, the last value in "enum insn_code". This made target reinitializing slow, so Richard S. changed the optab_handler index from insn_code to (insn_code - CODE_FOR_nothing) to allow the table to be memset to 0 (rather than filling it with CODE_FOR_nothing in a loop). I didn't like this solution very much, because of the casting between int and enum insn_code, and because it didn't solve the problem that CODE_FOR_nothing is target dependent. Also, comparisons against 0 are cheaper on probably all targets than comparing against a larger number (e.g. CODE_FOR_nothing is 2414 on powerpc64, 3013 on arm, and 3852 on x86_64), and there are a lot of compares against CODE_FOR_nothing. Therefore I propose this patch as an alternative (and IMHO better) solution, that changes things such that CODE_FOR_nothing==0. To achieve this, I introduced a dummy insn in insn_data, so insn-output.c's insn_data now starts with: const struct insn_data_d insn_data[] = { /* :0 */ { "*placeholder_for_nothing", #if HAVE_DESIGNATED_UNION_INITIALIZERS { 0 }, #else { 0, 0, 0 }, #endif 0, &operand_data[0], 0, 0, 0, 0, 0 }, Otherwise, there wasn't much to be changed. There was a sort-of bug in genpeep.c in that it was keeping its own sequence counter, but the rest is straight-forward. I get a small cc1 code size reduction: text data bss dec hex filename 14982747 639632 1223416 16845795 1010be3 build-patched/gcc/cc1 14983007 639704 1223416 16846127 1010d2f build-orig/gcc/cc1 I also get a small speedup, but nothing spectacular. Bootstrapped and tested on powerpc64-unknown-linux-gnu. OK for trunk? Ciao! Steven gcc/ 2012-07-09 Steven Bosscher * gensupport.c (init_rtx_reader_args_cb): Start counting code generating patterns from 1 to free up 0 for CODE_FOR_nothing. * gencodes.c (main): Give CODE_FOR_nothing the value 0. Add the LAST_INSN_CODE marker at the end. * genoutput.c (nothing): New static struct data. (idata): Initialize to ¬hing. (idata_end): Initialize to ¬hing.next. (init_insn_for_nothing): New function to create dummy 'nothing' insn. (main): Use it. * genpeep.c (insn_code_number): Remove global variable. (gen_peephole): Take it as an argument instead. (main): Take insn_code_number from read_md_rtx. * optabs.h: Revert r161809: (optab_handlers): Change type of insn_code back to insn_code. (optab_handler, widening_optab_handler, set_optab_handler, set_widening_optab_handler, convert_optab_handler, set_convert_optab_handler, direct_optab_handler, set_direct_optab_handler): Remove int casts. Revert to treating the insn_code field as "insn_code". --- gcc-4.7.1/gcc/gencodes.c.~1~ 2011-01-03 21:52:22.000000000 +0100 +++ gcc-4.7.1/gcc/gencodes.c 2012-07-15 11:35:30.000000000 +0200 @@ -2,7 +2,7 @@ - some macros CODE_FOR_... giving the insn_code_number value for each of the defined standard insn names. Copyright (C) 1987, 1991, 1995, 1998, 1999, 2000, 2001, 2003, - 2004, 2007, 2010 Free Software Foundation, Inc. + 2004, 2007, 2010, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -68,7 +68,8 @@ main (int argc, char **argv) #ifndef GCC_INSN_CODES_H\n\ #define GCC_INSN_CODES_H\n\ \n\ -enum insn_code {"); +enum insn_code {\n\ + CODE_FOR_nothing = 0,\n"); /* Read the machine description. */ @@ -85,7 +86,7 @@ enum insn_code {"); gen_insn (desc, insn_code_number); } - puts (" CODE_FOR_nothing\n\ + puts (" LAST_INSN_CODE\n\ };\n\ \n\ #endif /* GCC_INSN_CODES_H */"); --- gcc-4.7.1/gcc/genoutput.c.~1~ 2011-07-21 16:48:03.000000000 +0200 +++ gcc-4.7.1/gcc/genoutput.c 2012-07-15 11:35:30.000000000 +0200 @@ -1,6 +1,7 @@ /* Generate code from to output assembler insns as recognized from rtl. Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002, - 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2012 + Free Software Foundation, Inc. This file is part of GCC. @@ -171,9 +172,16 @@ struct data struct operand_data operand[MAX_MAX_OPERANDS]; }; +/* A dummy insn, for CODE_FOR_nothing. */ +static struct data nothing; + /* This variable points to the first link in the insn chain. */ +static struct data *idata = ¬hing; + +/* This variable points to the end of the insn chain. This is where + everything relevant from the machien description is appended to. */ +static struct data **idata_end = ¬hing.next; -static struct data *idata, **idata_end = &idata; static void output_prologue (void); static void output_operand_data (void); @@ -991,6 +999,14 @@ gen_split (rtx split, int lineno) place_operands (d); } +static void +init_insn_for_nothing (void) +{ + memset (¬hing, 0, sizeof (nothing)); + nothing.name = "*placeholder_for_nothing"; + nothing.filename = ""; +} + extern int main (int, char **); int @@ -1000,11 +1016,12 @@ main (int argc, char **argv) progname = "genoutput"; + init_insn_for_nothing (); + if (!init_rtx_reader_args (argc, argv)) return (FATAL_EXIT_CODE); output_prologue (); - next_code_number = 0; next_index_number = 0; /* Read the machine description. */ --- gcc-4.7.1/gcc/genpeep.c.~1~ 2010-11-30 17:36:19.000000000 +0100 +++ gcc-4.7.1/gcc/genpeep.c 2012-07-15 11:35:30.000000000 +0200 @@ -1,6 +1,6 @@ /* Generate code from machine description to perform peephole optimizations. Copyright (C) 1987, 1989, 1992, 1997, 1998, 1999, 2000, 2003, 2004, - 2007, 2010 Free Software Foundation, Inc. + 2007, 2010, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -47,18 +47,13 @@ static int max_opno; static int n_operands; -/* Peephole optimizations get insn codes just like insn patterns. - Count them so we know the code of the define_peephole we are handling. */ - -static int insn_code_number = 0; - -static void gen_peephole (rtx); +static void gen_peephole (rtx, int); static void match_rtx (rtx, struct link *, int); static void print_path (struct link *); static void print_code (RTX_CODE); static void -gen_peephole (rtx peep) +gen_peephole (rtx peep, int insn_code_number) { int ninsns = XVECLEN (peep, 0); int i; @@ -396,24 +391,15 @@ from the machine description file `md'. while (1) { - int line_no, rtx_number = 0; + int line_no; + int insn_code_number; - desc = read_md_rtx (&line_no, &rtx_number); + desc = read_md_rtx (&line_no, &insn_code_number); if (desc == NULL) break; - if (GET_CODE (desc) == DEFINE_PEEPHOLE) - { - gen_peephole (desc); - insn_code_number++; - } - if (GET_CODE (desc) == DEFINE_INSN - || GET_CODE (desc) == DEFINE_EXPAND - || GET_CODE (desc) == DEFINE_SPLIT - || GET_CODE (desc) == DEFINE_PEEPHOLE2) - { - insn_code_number++; - } + if (GET_CODE (desc) == DEFINE_PEEPHOLE) + gen_peephole (desc, insn_code_number); } printf (" return 0;\n}\n\n"); --- gcc-4.7.1/gcc/gensupport.c.~1~ 2011-06-21 16:38:38.000000000 +0200 +++ gcc-4.7.1/gcc/gensupport.c 2012-07-15 11:35:30.000000000 +0200 @@ -1,6 +1,6 @@ /* Support routines for the various generation passes. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, Free Software Foundation, Inc. + 2010, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -38,6 +38,10 @@ int insn_elision = 1; static struct obstack obstack; struct obstack *rtl_obstack = &obstack; +/* Counter for patterns that generate code: define_insn, define_expand, + define_split, define_peephole, and define_peephole2. See read_md_rtx(). + Any define_insn_and_splits are already in separate queues so that the + insn and the splitter get a unique number also. */ static int sequence_num; static int predicable_default; @@ -1397,7 +1401,9 @@ init_rtx_reader_args_cb (int argc, char condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL); init_predicate_table (); obstack_init (rtl_obstack); - sequence_num = 0; + + /* Start at 1, to make 0 available for CODE_FOR_nothing. */ + sequence_num = 1; read_md_files (argc, argv, parse_opt, rtx_handle_directive); @@ -1419,7 +1425,11 @@ init_rtx_reader_args (int argc, char **a return init_rtx_reader_args_cb (argc, argv, 0); } -/* The entry point for reading a single rtx from an md file. */ +/* The entry point for reading a single rtx from an md file. Return + the rtx, or NULL if the md file has been fully processed. + Return the line where the rtx was found in LINENO. + Return the number of code generating rtx'en read since the start + of the md file in SEQNR. */ rtx read_md_rtx (int *lineno, int *seqnr) --- gcc-4.7.1/gcc/optabs.h.~1~ 2012-01-17 21:37:46.000000000 +0100 +++ gcc-4.7.1/gcc/optabs.h 2012-07-15 11:35:30.000000000 +0200 @@ -1,6 +1,6 @@ /* Definitions for code generation pass of GNU compiler. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -29,6 +29,10 @@ along with GCC; see the file COPYING3. For example, add_optab applies to addition. + The insn_code slot is the enum insn_code that says how to + generate an insn for this operation on a particular machine mode. + It is CODE_FOR_nothing if there is no such insn on the target machine. + The `lib_call' slot is the name of the library function that can be used to perform the operation. @@ -36,10 +40,7 @@ along with GCC; see the file COPYING3. struct optab_handlers { - /* I - CODE_FOR_nothing, where I is either the insn code of the - associated insn generator or CODE_FOR_nothing if there is no such - insn on the target machine. */ - int insn_code; + enum insn_code insn_code; }; struct widening_optab_handlers @@ -1011,8 +1012,7 @@ extern rtx expand_vec_perm (enum machine static inline enum insn_code optab_handler (optab op, enum machine_mode mode) { - return (enum insn_code) (op->handlers[(int) mode].insn_code - + (int) CODE_FOR_nothing); + return op->handlers[(int) mode].insn_code; } /* Like optab_handler, but for widening_operations that have a TO_MODE and @@ -1026,8 +1026,7 @@ widening_optab_handler (optab op, enum m return optab_handler (op, to_mode); if (op->widening) - return (enum insn_code) (op->widening->handlers[(int) to_mode][(int) from_mode].insn_code - + (int) CODE_FOR_nothing); + return op->widening->handlers[(int) to_mode][(int) from_mode].insn_code; return CODE_FOR_nothing; } @@ -1037,7 +1036,7 @@ widening_optab_handler (optab op, enum m static inline void set_optab_handler (optab op, enum machine_mode mode, enum insn_code code) { - op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing; + op->handlers[(int) mode].insn_code = code; } /* Like set_optab_handler, but for widening operations that have a TO_MODE @@ -1055,8 +1054,7 @@ set_widening_optab_handler (optab op, en op->widening = (struct widening_optab_handlers *) xcalloc (1, sizeof (struct widening_optab_handlers)); - op->widening->handlers[(int) to_mode][(int) from_mode].insn_code - = (int) code - (int) CODE_FOR_nothing; + op->widening->handlers[(int) to_mode][(int) from_mode].insn_code = code; } } @@ -1068,9 +1066,7 @@ static inline enum insn_code convert_optab_handler (convert_optab op, enum machine_mode to_mode, enum machine_mode from_mode) { - return ((enum insn_code) - (op->handlers[(int) to_mode][(int) from_mode].insn_code - + (int) CODE_FOR_nothing)); + return op->handlers[(int) to_mode][(int) from_mode].insn_code; } /* Record that insn CODE should be used to perform conversion OP @@ -1080,8 +1076,7 @@ static inline void set_convert_optab_handler (convert_optab op, enum machine_mode to_mode, enum machine_mode from_mode, enum insn_code code) { - op->handlers[(int) to_mode][(int) from_mode].insn_code - = (int) code - (int) CODE_FOR_nothing; + op->handlers[(int) to_mode][(int) from_mode].insn_code = code; } /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing @@ -1090,8 +1085,7 @@ set_convert_optab_handler (convert_optab static inline enum insn_code direct_optab_handler (direct_optab op, enum machine_mode mode) { - return (enum insn_code) (op->handlers[(int) mode].insn_code - + (int) CODE_FOR_nothing); + return op->handlers[(int) mode].insn_code; } /* Record that insn CODE should be used to implement mode MODE of OP. */ @@ -1100,7 +1094,7 @@ static inline void set_direct_optab_handler (direct_optab op, enum machine_mode mode, enum insn_code code) { - op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing; + op->handlers[(int) mode].insn_code = code; } extern rtx optab_libfunc (optab optab, enum machine_mode mode);