aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/loongarch/loongarch.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/loongarch/loongarch.cc')
-rw-r--r--gcc/config/loongarch/loongarch.cc91
1 files changed, 85 insertions, 6 deletions
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index c90b701..6b92e70 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -7570,15 +7570,19 @@ loongarch_global_init (void)
loongarch_dwarf_regno[i] = INVALID_REGNUM;
}
+ /* Function to allocate machine-dependent function status. */
+ init_machine_status = &loongarch_init_machine_status;
+};
+
+static void
+loongarch_reg_init (void)
+{
/* Set up loongarch_hard_regno_mode_ok. */
for (int mode = 0; mode < MAX_MACHINE_MODE; mode++)
for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
loongarch_hard_regno_mode_ok_p[mode][regno]
= loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode);
-
- /* Function to allocate machine-dependent function status. */
- init_machine_status = &loongarch_init_machine_status;
-};
+}
static void
loongarch_option_override_internal (struct loongarch_target *target,
@@ -7605,20 +7609,92 @@ loongarch_option_override_internal (struct loongarch_target *target,
/* Override some options according to the resolved target. */
loongarch_target_option_override (target, opts, opts_set);
+
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (opts, opts_set);
+
+ loongarch_reg_init ();
+}
+
+/* Remember the last target of loongarch_set_current_function. */
+
+static GTY(()) tree loongarch_previous_fndecl;
+
+/* Restore or save the TREE_TARGET_GLOBALS from or to new_tree.
+ Used by loongarch_set_current_function to
+ make sure optab availability predicates are recomputed when necessary. */
+
+static void
+loongarch_save_restore_target_globals (tree new_tree)
+{
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else if (new_tree == target_option_default_node)
+ restore_target_globals (&default_target_globals);
+ else
+ TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+}
+
+/* Implement TARGET_SET_CURRENT_FUNCTION. */
+
+static void
+loongarch_set_current_function (tree fndecl)
+{
+ if (fndecl == loongarch_previous_fndecl)
+ return;
+
+ tree old_tree;
+ if (loongarch_previous_fndecl == NULL_TREE)
+ old_tree = target_option_current_node;
+ else if (DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl))
+ old_tree = DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl);
+ else
+ old_tree = target_option_default_node;
+
+ if (fndecl == NULL_TREE)
+ {
+ if (old_tree != target_option_current_node)
+ {
+ loongarch_previous_fndecl = NULL_TREE;
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION
+ (target_option_current_node));
+ }
+ return;
+ }
+
+ tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (new_tree == NULL_TREE)
+ new_tree = target_option_default_node;
+
+ loongarch_previous_fndecl = fndecl;
+
+ if (new_tree == old_tree)
+ return;
+
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (new_tree));
+
+ loongarch_reg_init ();
+
+ loongarch_save_restore_target_globals (new_tree);
}
+
+
/* Implement TARGET_OPTION_OVERRIDE. */
static void
loongarch_option_override (void)
{
+ /* Global initializations. */
+ loongarch_global_init ();
+
/* Setting up the target configuration. */
loongarch_option_override_internal (&la_target,
&global_options,
&global_options_set);
- /* Global initializations. */
- loongarch_global_init ();
}
/* Implement TARGET_OPTION_SAVE. */
@@ -10935,6 +11011,9 @@ loongarch_asm_code_end (void)
#undef TARGET_OPTION_RESTORE
#define TARGET_OPTION_RESTORE loongarch_option_restore
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION loongarch_set_current_function
+
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address