@@ -2512,14 +2512,11 @@ loongarch_init_builtins (void)
for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++)
{
d = &loongarch_builtins[i];
- if (d->avail ())
- {
- type = loongarch_build_function_type (d->function_type);
- loongarch_builtin_decls[i]
- = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL,
- NULL);
- loongarch_get_builtin_decl_index[d->icode] = i;
- }
+ type = loongarch_build_function_type (d->function_type);
+ loongarch_builtin_decls[i]
+ = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL,
+ NULL);
+ loongarch_get_builtin_decl_index[d->icode] = i;
}
}
@@ -3105,15 +3102,21 @@ loongarch_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
tree fndecl;
- unsigned int fcode, avail;
+ unsigned int fcode;
const struct loongarch_builtin_description *d;
fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
fcode = DECL_MD_FUNCTION_CODE (fndecl);
gcc_assert (fcode < ARRAY_SIZE (loongarch_builtins));
d = &loongarch_builtins[fcode];
- avail = d->avail ();
- gcc_assert (avail != 0);
+
+ if (!d->avail ())
+ {
+ error_at (EXPR_LOCATION (exp),
+ "built-in function %qD is not enabled", fndecl);
+ return target;
+ }
+
switch (d->builtin_type)
{
case LARCH_BUILTIN_DIRECT:
@@ -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
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
#include "config/loongarch/loongarch-opts.h"
+#define SWITCHABLE_TARGET 1
+
#define TARGET_SUPPORTS_WIDE_INT 1
/* Macros to silence warnings about numbers being signed in traditional
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-require-effective-target loongarch_sx_as } */
+/* { dg-lto-do link } */
+/* { dg-skip-if "" { ! { loongarch*-linux-* } } } */
+/* { dg-lto-options { {-mlsx } } } */
+/* { dg-suppress-ld-options { -mlsx } } */
+
+#include <lsxintrin.h>
+
+int main (void)
+{
+ __m128i a, b, c;
+ c = __lsx_vand_v (a, b);
+ return 0;
+}
@@ -13402,6 +13402,18 @@ proc check_effective_target_loongarch_sx { } {
} "-mlsx"]
}
+proc check_effective_target_loongarch_sx_as { } {
+ return [check_no_compiler_messages loongarch_sx_as object {
+ #include <lsxintrin.h>
+ int main (void)
+ {
+ __m128i a, b, c;
+ c = __lsx_vand_v (a, b);
+ return 0;
+ }
+ } "-mlsx"]
+}
+
proc check_effective_target_loongarch_sx_hw { } {
return [check_runtime loongarch_sx_hw {
#include <lsxintrin.h>