From: Lulu Cheng Date: Wed, 24 Sep 2025 06:49:53 +0000 (+0800) Subject: LoongArch: Implement TARGET_CAN_INLINE_P[PR121875]. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d6ee89a65bd98b14940245ec79814ae3d38b0121;p=thirdparty%2Fgcc.git LoongArch: Implement TARGET_CAN_INLINE_P[PR121875]. Because LoongArch does not implement TARGET_CAN_INLINE_P, functions with the target attribute set and those without it cannot be inlined. At the same time, setting the always_inline attribute will cause compilation failure. To solve this problem, I implemented this hook. During the implementation process, it checks the status of the target special options of the caller and callee, such as the ISA extension. PR target/121875 gcc/ChangeLog: * config/loongarch/loongarch.cc (loongarch_can_inline_p): New function. (TARGET_CAN_INLINE_P): Define. gcc/testsuite/ChangeLog: * gcc.target/loongarch/can_inline_1.c: New test. * gcc.target/loongarch/can_inline_2.c: New test. * gcc.target/loongarch/can_inline_3.c: New test. * gcc.target/loongarch/can_inline_4.c: New test. * gcc.target/loongarch/can_inline_5.c: New test. * gcc.target/loongarch/can_inline_6.c: New test. * gcc.target/loongarch/pr121875.c: New test. --- diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index ef5d5f4e060..4d82fc8b6ec 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -11202,6 +11202,69 @@ loongarch_compute_pressure_classes (reg_class *classes) return i; } +/* Implement TARGET_CAN_INLINE_P. Determine whether inlining the function + CALLER into the function CALLEE is safe. Inlining should be rejected if + there is no always_inline attribute and the target options differ except + for differences in ISA extensions or performance tuning options like the + code model, TLS dialect, etc. */ + +static bool +loongarch_can_inline_p (tree caller, tree callee) +{ + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee); + tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller); + + if (!callee_tree) + callee_tree = target_option_default_node; + + if (!caller_tree) + caller_tree = target_option_default_node; + + /* If both caller and callee have attributes, assume that if the + pointer is different, the two functions have different target + options since build_target_option_node uses a hash table for the + options. */ + if (callee_tree == caller_tree) + return true; + + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree); + + /* Callee and caller should have the same target options. */ + int callee_target_flags = callee_opts->x_target_flags; + int caller_target_flags = caller_opts->x_target_flags; + + if (callee_target_flags != caller_target_flags) + return false; + + /* If callee enables the isa extension that the caller does not enable, + inlining is disabled. */ + if (~caller_opts->x_la_isa_evolution + & callee_opts->x_la_isa_evolution) + return false; + + /* If simd extensions are enabled for the callee but not for the caller, + inlining is disabled. */ + if ((caller_opts->x_la_opt_simd == ISA_EXT_NONE + && callee_opts->x_la_opt_simd != ISA_EXT_NONE) + || (caller_opts->x_la_opt_simd == ISA_EXT_SIMD_LSX + && callee_opts->x_la_opt_simd == ISA_EXT_SIMD_LASX)) + return false; + + bool always_inline + = lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee)); + + /* If the architectural features match up and the callee is always_inline + then the other attributes don't matter. */ + if (always_inline) + return true; + + if (caller_opts->x_la_opt_cmodel != callee_opts->x_la_opt_cmodel) + return false; + + return true; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -11482,6 +11545,9 @@ loongarch_compute_pressure_classes (reg_class *classes) #undef TARGET_COMPUTE_PRESSURE_CLASSES #define TARGET_COMPUTE_PRESSURE_CLASSES loongarch_compute_pressure_classes +#undef TARGET_CAN_INLINE_P +#define TARGET_CAN_INLINE_P loongarch_can_inline_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-loongarch.h" diff --git a/gcc/testsuite/gcc.target/loongarch/can_inline_1.c b/gcc/testsuite/gcc.target/loongarch/can_inline_1.c new file mode 100644 index 00000000000..a1726d7f089 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/can_inline_1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */ +/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */ +/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */ + +void +__attribute__ ((target ("lsx"))) +foo (void) +{} + +void +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/loongarch/can_inline_2.c b/gcc/testsuite/gcc.target/loongarch/can_inline_2.c new file mode 100644 index 00000000000..0d77aca6c76 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/can_inline_2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */ +/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */ +/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */ + +void +__attribute__ ((target ("lasx"))) +foo (void) +{} + +void +__attribute__ ((target ("lsx"))) +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/loongarch/can_inline_3.c b/gcc/testsuite/gcc.target/loongarch/can_inline_3.c new file mode 100644 index 00000000000..d11dc4707fb --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/can_inline_3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */ +/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */ +/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */ + +void +__attribute__ ((target ("arch=la64v1.1"))) +foo (void) +{} + +void +__attribute__ ((target ("arch=la64v1.0"))) +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/loongarch/can_inline_4.c b/gcc/testsuite/gcc.target/loongarch/can_inline_4.c new file mode 100644 index 00000000000..6274ff10a7f --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/can_inline_4.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */ +/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */ +/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */ + +void +foo (void) +{} + +void +__attribute__ ((target ("cmodel=extreme"))) +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/loongarch/can_inline_5.c b/gcc/testsuite/gcc.target/loongarch/can_inline_5.c new file mode 100644 index 00000000000..88550268e97 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/can_inline_5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */ +/* { dg-final { scan-tree-dump {\(inlined\)} "einline" } } */ + +void +__attribute__ ((always_inline)) +inline +foo (void) +{} + +void +__attribute__ ((target ("cmodel=extreme"))) +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/loongarch/can_inline_6.c b/gcc/testsuite/gcc.target/loongarch/can_inline_6.c new file mode 100644 index 00000000000..b700de263a3 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/can_inline_6.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */ +/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */ +/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */ + +void +__attribute__ ((target ("strict-align"))) +foo (void) +{} + +void +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/loongarch/pr121875.c b/gcc/testsuite/gcc.target/loongarch/pr121875.c new file mode 100644 index 00000000000..f0a42ba020a --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/pr121875.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-march=loongarch64 -mabi=lp64d -O2" } */ + +[[gnu::always_inline]] inline void f() {} +[[gnu::target("lasx")]] int main() {f();}