aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2013-02-19 00:04:49 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2013-02-19 00:04:49 +0000
commit135204ddd3bf1f3885db364c109bf977f5067e8f (patch)
tree7a29bd18e10dbd4f5b64765ae5b8f07a5bda81db /gcc/optabs.c
parentf6007d99f88822a517d15c6e56dcbfa66e8b5dec (diff)
downloadgcc-135204ddd3bf1f3885db364c109bf977f5067e8f.zip
gcc-135204ddd3bf1f3885db364c109bf977f5067e8f.tar.gz
gcc-135204ddd3bf1f3885db364c109bf977f5067e8f.tar.bz2
re PR target/52555 (ICE unrecognizable insn with -ffast-math and __attribute__((optimize(xx))))
PR target/52555 * genopinit.c (raw_optab_handler): Use this_fn_optabs. (swap_optab_enable): Same. (init_all_optabs): Use argument instead of global. * tree.h (struct tree_optimization_option): New field target_optabs. * expr.h (init_all_optabs): Add argument to prototype. (TREE_OPTIMIZATION_OPTABS): New. (save_optabs_if_changed): Protoize. * optabs.h: Declare this_fn_optabs. * optabs.c (save_optabs_if_changed): New. Declare this_fn_optabs. (init_optabs): Add argument to init_all_optabs() call. * function.c (invoke_set_current_function_hook): Handle per function optabs. * function.h (struct function): New field optabs. * config/mips/mips.c (mips_set_mips16_mode): Handle when optimization_current_node has changed. * target-globals.h (save_target_globals_default_opts): Protoize. * target-globals.c (save_target_globals_default_opts): New. c-family/ * c-common.c (handle_optimize_attribute): Call save_optabs_if_changed. Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r196129
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index c1dacf4..c5778d1 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
struct target_optabs default_target_optabs;
struct target_libfuncs default_target_libfuncs;
+struct target_optabs *this_fn_optabs = &default_target_optabs;
#if SWITCHABLE_TARGET
struct target_optabs *this_target_optabs = &default_target_optabs;
struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
@@ -6150,7 +6151,7 @@ init_optabs (void)
libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
/* Fill in the optabs with the insns we support. */
- init_all_optabs ();
+ init_all_optabs (this_fn_optabs);
/* The ffs function operates on `int'. Fall back on it if we do not
have a libgcc2 function for that width. */
@@ -6207,6 +6208,38 @@ init_optabs (void)
targetm.init_libfuncs ();
}
+/* Recompute the optabs and save them if they have changed. */
+
+void
+save_optabs_if_changed (tree fndecl)
+{
+ /* ?? 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);
+
+ struct target_optabs *tmp_optabs = (struct target_optabs *)
+ ggc_alloc_atomic (sizeof (struct target_optabs));
+ tree optnode = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+ /* 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;
+ }
+ else
+ {
+ TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
+ ggc_free (tmp_optabs);
+ }
+}
+
/* A helper function for init_sync_libfuncs. Using the basename BASE,
install libfuncs into TAB for BASE_N for 1 <= N <= MAX. */