From 4b1baac81ff353bf0e3cea5c972a864db361355c Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 9 Mar 2013 07:54:02 +0000 Subject: [PATCH] re PR middle-end/56524 (Compiler ICE when compiling with -mips16) gcc/ PR middle-end/56524 * tree.h (tree_optimization_option): Rename target_optabs to optabs. Add base_optabs. (TREE_OPTIMIZATION_OPTABS): Update after previous field change. (TREE_OPTIMIZATION_BASE_OPTABS): New macro. (save_optabs_if_changed): Replace with... (init_tree_optimization_optabs): ...this. * optabs.c (save_optabs_if_changed): Rename to... (init_tree_optimization_optabs): ...this. Take the optimization node as argument. Do nothing if the base optabs are already correct. Reuse the existing TREE_OPTIMIZATION_OPTABS memory if we need to recompute optabs. * function.h (function): Remove optabs field. * function.c (invoke_set_current_function_hook): Call init_tree_optimization_optabs. Use the result to initialize this_fn_optabs. gcc/c-family/ PR middle-end/56524 * c-common.c (handle_optimize_attribute): Don't call save_optabs_if_changed. gcc/testsuite/ PR middle-end/56524 * gcc.target/mips/pr56524.c: New test. From-SVN: r196570 --- gcc/ChangeLog | 19 ++++++++++++++++ gcc/c-family/ChangeLog | 6 +++++ gcc/c-family/c-common.c | 2 -- gcc/function.c | 23 +++++--------------- gcc/function.h | 3 --- gcc/optabs.c | 29 +++++++++++++------------ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/mips/pr56524.c | 8 +++++++ gcc/tree.h | 15 ++++++++----- 9 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/pr56524.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7a4de2537e7..3ae6c4c84b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2013-03-09 Richard Sandiford + + PR middle-end/56524 + * tree.h (tree_optimization_option): Rename target_optabs to optabs. + Add base_optabs. + (TREE_OPTIMIZATION_OPTABS): Update after previous field change. + (TREE_OPTIMIZATION_BASE_OPTABS): New macro. + (save_optabs_if_changed): Replace with... + (init_tree_optimization_optabs): ...this. + * optabs.c (save_optabs_if_changed): Rename to... + (init_tree_optimization_optabs): ...this. Take the optimization node + as argument. Do nothing if the base optabs are already correct. + Reuse the existing TREE_OPTIMIZATION_OPTABS memory if we need + to recompute optabs. + * function.h (function): Remove optabs field. + * function.c (invoke_set_current_function_hook): Call + init_tree_optimization_optabs. Use the result to initialize + this_fn_optabs. + 2013-02-27 Aldy Hernandez * trans-mem.c (expand_transaction): Do not set PR_INSTRUMENTEDCODE diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 6d90bfb37d2..dd6cb296a44 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2013-03-09 Richard Sandiford + + PR middle-end/56524 + * c-common.c (handle_optimize_attribute): Don't call + save_optabs_if_changed. + 2013-03-05 Jakub Jelinek PR middle-end/56461 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index d01de3e40d5..c7cdd0fc7a0 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8947,8 +8947,6 @@ handle_optimize_attribute (tree *node, tree name, tree args, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = build_optimization_node (); - save_optabs_if_changed (*node); - /* Restore current options. */ cl_optimization_restore (&global_options, &cur_opts); } diff --git a/gcc/function.c b/gcc/function.c index 1b41cf2cb34..e673f21a57d 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4400,25 +4400,14 @@ invoke_set_current_function_hook (tree fndecl) } targetm.set_current_function (fndecl); + this_fn_optabs = this_target_optabs; - if (opts == optimization_default_node) - this_fn_optabs = this_target_optabs; - else + if (opts != optimization_default_node) { - struct function *fn = DECL_STRUCT_FUNCTION (fndecl); - if (fn->optabs == NULL) - { - if (this_target_optabs == &default_target_optabs) - fn->optabs = TREE_OPTIMIZATION_OPTABS (opts); - else - { - fn->optabs = (unsigned char *) - ggc_alloc_atomic (sizeof (struct target_optabs)); - init_all_optabs ((struct target_optabs *) fn->optabs); - } - } - this_fn_optabs = fn->optabs ? (struct target_optabs *) fn->optabs - : this_target_optabs; + init_tree_optimization_optabs (opts); + if (TREE_OPTIMIZATION_OPTABS (opts)) + this_fn_optabs = (struct target_optabs *) + TREE_OPTIMIZATION_OPTABS (opts); } } } diff --git a/gcc/function.h b/gcc/function.h index 53e28b768c0..89d71e592dd 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -580,9 +580,6 @@ struct GTY(()) function { a string describing the reason for failure. */ const char * GTY((skip)) cannot_be_copied_reason; - /* Optabs for this function. This is of type `struct target_optabs *'. */ - unsigned char *GTY ((atomic)) optabs; - /* Collected bit flags. */ /* Number of units of general registers that need saving in stdarg diff --git a/gcc/optabs.c b/gcc/optabs.c index c5778d1928b..a3051ad9d9a 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6208,31 +6208,32 @@ init_optabs (void) targetm.init_libfuncs (); } -/* Recompute the optabs and save them if they have changed. */ +/* Use the current target and options to initialize + TREE_OPTIMIZATION_OPTABS (OPTNODE). */ void -save_optabs_if_changed (tree fndecl) +init_tree_optimization_optabs (tree optnode) { - /* ?? If this fails, we should temporarily restore the default - target first (set_cfun (NULL) ??), do the rest of this function, - and then restore it. */ - gcc_assert (this_target_optabs == &default_target_optabs); + /* Quick exit if we have already computed optabs for this target. */ + if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs) + return; + /* Forget any previous information and set up for the current target. */ + TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs; struct target_optabs *tmp_optabs = (struct target_optabs *) - ggc_alloc_atomic (sizeof (struct target_optabs)); - tree optnode = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + TREE_OPTIMIZATION_OPTABS (optnode); + if (tmp_optabs) + memset (tmp_optabs, 0, sizeof (struct target_optabs)); + else + tmp_optabs = (struct target_optabs *) + ggc_alloc_atomic (sizeof (struct target_optabs)); /* Generate a new set of optabs into tmp_optabs. */ init_all_optabs (tmp_optabs); /* If the optabs changed, record it. */ if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs))) - { - if (TREE_OPTIMIZATION_OPTABS (optnode)) - ggc_free (TREE_OPTIMIZATION_OPTABS (optnode)); - - TREE_OPTIMIZATION_OPTABS (optnode) = (unsigned char *) tmp_optabs; - } + TREE_OPTIMIZATION_OPTABS (optnode) = (unsigned char *) tmp_optabs; else { TREE_OPTIMIZATION_OPTABS (optnode) = NULL; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b1043301fa3..15156f7ae8c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-03-09 Richard Sandiford + + PR middle-end/56524 + * gcc.target/mips/pr56524.c: New test. + 2013-03-08 Paolo Carlini PR c++/56565 diff --git a/gcc/testsuite/gcc.target/mips/pr56524.c b/gcc/testsuite/gcc.target/mips/pr56524.c new file mode 100644 index 00000000000..7df021b6998 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr56524.c @@ -0,0 +1,8 @@ +/* { dg-options "-mips16" } */ + +void bar (void) {} + +void __attribute__((optimize("schedule-insns"))) +foo (void) +{ +} diff --git a/gcc/tree.h b/gcc/tree.h index 740d4382712..b852f1d9434 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3589,21 +3589,26 @@ struct GTY(()) tree_optimization_option { /* Target optabs for this set of optimization options. This is of type `struct target_optabs *'. */ - unsigned char *GTY ((atomic)) target_optabs; + unsigned char *GTY ((atomic)) optabs; + + /* The value of this_target_optabs against which the optabs above were + generated. */ + struct target_optabs *GTY ((skip)) base_optabs; }; #define TREE_OPTIMIZATION(NODE) \ (&OPTIMIZATION_NODE_CHECK (NODE)->optimization.opts) #define TREE_OPTIMIZATION_OPTABS(NODE) \ - (OPTIMIZATION_NODE_CHECK (NODE)->optimization.target_optabs) + (OPTIMIZATION_NODE_CHECK (NODE)->optimization.optabs) + +#define TREE_OPTIMIZATION_BASE_OPTABS(NODE) \ + (OPTIMIZATION_NODE_CHECK (NODE)->optimization.base_optabs) /* Return a tree node that encapsulates the current optimization options. */ extern tree build_optimization_node (void); -/* Save a new set of target_optabs in a TREE_OPTIMIZATION node if the - current set of optabs has changed. */ -extern void save_optabs_if_changed (tree); +extern void init_tree_optimization_optabs (tree); /* Target options used by a function. */