From: Matthew Fortune <matthew.fort...@imgtec.com> Add a CLI option and an inline_intermix function attribute to ignore ISA differences between a caller and a callee. The format of this attribute is __attribute__((inline_intermix(yes|no))).
gcc/ * doc/extend.texi: Document inline_intermix. * config/mips/mips.cc (mips_attribute_table): Add inline_intermix. (mips_handle_inline_intermix_attr): New function. (mips_get_inline_intermix_attr): Likewise. (mips_can_inline_p): Use mips_get_inline_intermix_attr. gcc/testsuite/ * gcc.target/mips/mips.exp: Add -m[no-]inline-intermix. * gcc.target/mips/inline-intermix-1.c: New file. * gcc.target/mips/inline-intermix-2.c: Likewise. * gcc.target/mips/inline-intermix-3.c: Likewise. * gcc.target/mips/inline-intermix-4.c: Likewise. Cherry-picked 02c76fc61198186af09fd9c4c0ef7352ab6511ad and ae484b9431e5bd407e09b66392a1882b6878e4de from https://github.com/MIPS/gcc Signed-off-by: Matthew Fortune <matthew.fort...@imgtec.com> Signed-off-by: Faraz Shahbazker <fshahbaz...@wavecomp.com> Signed-off-by: Aleksandar Rakic <aleksandar.ra...@htecgroup.com> --- gcc/config/mips/mips.cc | 72 ++++++++++++++++++- gcc/config/mips/mips.opt | 4 ++ gcc/doc/extend.texi | 17 +++++ gcc/doc/invoke.texi | 12 ++++ .../gcc.target/mips/inline-intermix-1.c | 13 ++++ .../gcc.target/mips/inline-intermix-2.c | 13 ++++ .../gcc.target/mips/inline-intermix-3.c | 13 ++++ .../gcc.target/mips/inline-intermix-4.c | 13 ++++ gcc/testsuite/gcc.target/mips/mips.exp | 1 + 9 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/mips/inline-intermix-1.c create mode 100644 gcc/testsuite/gcc.target/mips/inline-intermix-2.c create mode 100644 gcc/testsuite/gcc.target/mips/inline-intermix-3.c create mode 100644 gcc/testsuite/gcc.target/mips/inline-intermix-4.c diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 9808fda286c..e8ed002dfed 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -607,6 +607,7 @@ const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = { }; static tree mips_handle_code_readable_attr (tree *, tree, tree, int, bool *); +static tree mips_handle_inline_intermix_attr (tree *, tree, tree, int, bool *); static tree mips_handle_interrupt_attr (tree *, tree, tree, int, bool *); static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int, bool *); @@ -627,6 +628,8 @@ TARGET_GNU_ATTRIBUTES (mips_attribute_table, { { "nomips16", 0, 0, true, false, false, false, NULL, NULL }, { "micromips", 0, 0, true, false, false, false, NULL, NULL }, { "nomicromips", 0, 0, true, false, false, false, NULL, NULL }, + { "inline_intermix", 0, 1, true, false, false, false, + mips_handle_inline_intermix_attr, NULL }, { "nocompression", 0, 0, true, false, false, false, NULL, NULL }, { "code_readable", 0, 1, true, false, false, false, mips_handle_code_readable_attr, NULL }, @@ -770,6 +773,7 @@ static const struct attr_desc mips_func_opt_list_strings[] = { {"hot", 0, FOL_ARG_NONE, 1 << FOLC_COLD }, {"cold", 0, FOL_ARG_NONE, 1 << FOLC_HOT }, {"code_readable", 0, FOL_ARG_STRING, 0 }, + {"inline_intermix", 0, FOL_ARG_STRING, 0 }, {"alias", 0, FOL_ARG_STRING, 0 }, {"aligned", 0, FOL_ARG_SINGLE_NUM, 0}, {"alloc_size", 0, FOL_ARG_NUM_ONE_OR_TWO, 0}, @@ -1917,6 +1921,71 @@ mips_use_debug_exception_return_p (tree type) TYPE_ATTRIBUTES (type)) != NULL; } +/* Verify the arguments to an inline_intermix attribute. */ + +static tree +mips_handle_inline_intermix_attr (tree *node ATTRIBUTE_UNUSED, tree name, + tree args, int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + if (!is_attribute_p ("inline_intermix", name) || args == NULL) + return NULL_TREE; + + if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + warning (OPT_Wattributes, + "%qE attribute requires a string argument", name); + *no_add_attrs = true; + } + else if (strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "no") != 0 + && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "yes") != 0) + { + warning (OPT_Wattributes, + "argument to %qE attribute is neither no nor yes", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Determine the inline_intermix setting for a function if it has one. + When inline_intermix is used without an argument it is the same as + inline_intermix=yes. */ + +static bool +mips_get_inline_intermix_attr (tree decl) +{ + tree attr; + + if (decl == NULL) + return TARGET_INLINE_INTERMIX; + + attr = lookup_attribute ("inline_intermix", DECL_ATTRIBUTES (decl)); + + if (attr != NULL) + { + if (TREE_VALUE (attr) != NULL_TREE) + { + const char * str; + + str = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))); + if (strcmp (str, "no") == 0) + return false; + else if (strcmp (str, "yes") == 0) + return true; + + /* mips_handle_inline_intermix_attr will have verified the + arguments are correct before adding the attribute. */ + gcc_unreachable (); + } + + /* No argument is the same as inline_intermix=true like the + command line option -minline-intermix. */ + return true; + } + + return TARGET_INLINE_INTERMIX; +} /* Verify the arguments to a code_readable attribute. */ @@ -2294,7 +2363,8 @@ mips_merge_decl_attributes (tree olddecl, tree newdecl) static bool mips_can_inline_p (tree caller, tree callee) { - if (mips_get_compress_mode (callee) != mips_get_compress_mode (caller)) + if (mips_get_compress_mode (callee) != mips_get_compress_mode (caller) + && !mips_get_inline_intermix_attr (callee)) return false; return default_target_can_inline_p (caller, callee); } diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt index c5a3addbc55..222fdbfaf96 100644 --- a/gcc/config/mips/mips.opt +++ b/gcc/config/mips/mips.opt @@ -565,3 +565,7 @@ Target Undocumented Var(TARGET_USE_SAVE_RESTORE) Init(-1) muse-copyw-ucopyw Target Undocumented Var(TARGET_USE_COPYW_UCOPYW) Init(-1) + +minline-intermix +Target Var(TARGET_INLINE_INTERMIX) +Allow inlining even if the compression flags differ between caller and callee. diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c566474074d..76ebdf97a98 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -6005,6 +6005,23 @@ This function attribute instructs the compiler to generate a hazard barrier return that clears all execution and instruction hazards while returning, instead of generating a normal return instruction. +@item inline_intermix +@cindex @code{inline_intermix} function attribute, MIPS +On MIPS targets, you can use the @code{inline_intermix} attribute to override +the default inlining rule that prevents functions with different ISAs being +inlined. This can be helpful when the ISA selection is made for performance +or code density reasons instead of fundamental dependency on a specific ISA. +The attribute takes a single optional argument: + +@table @samp +@item no +The function must not be inlined into a function with a different ISA. +@item yes +The function can be inlined into a function with a different ISA. +@end table + +If there is no argument supplied, the default of @code{"yes"} applies. + @item code_readable @cindex @code{code_readable} function attribute, MIPS For MIPS targets that support PC-relative addressing modes, this attribute diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d607f8e430c..3560a7920a7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1125,6 +1125,7 @@ Objective-C and Objective-C++ Dialects}. -mips16 -mno-mips16 -mflip-mips16 -minterlink-compressed -mno-interlink-compressed -minterlink-mips16 -mno-interlink-mips16 +-minline-intermix -mno-inline-intermix -mabi=@var{abi} -mabicalls -mno-abicalls -mshared -mno-shared -mplt -mno-plt -mxgot -mno-xgot -mgp32 -mgp64 -mfp32 -mfpxx -mfp64 -mhard-float -msoft-float @@ -28363,6 +28364,17 @@ Aliases of @option{-minterlink-compressed} and @option{-mno-interlink-compressed}. These options predate the microMIPS ASE and are retained for backwards compatibility. +@opindex minline-intermix +@opindex mno-inline-intermix +@item -minline-intermix +@itemx -mno-inline-intermix +Enable inlining of functions which have opposing mips16/nomips16 attributes. +This is useful when using the mips16 attribute to balance code size and +performance so that a function will be compressed when not inlined or +vice-versa. When using this option it is necessary to protect functions +that cannot be compiled as MIPS16 with a noinline attribute to ensure +they are not inlined into a MIPS16 function. + @opindex mabi @item -mabi=32 @itemx -mabi=o64 diff --git a/gcc/testsuite/gcc.target/mips/inline-intermix-1.c b/gcc/testsuite/gcc.target/mips/inline-intermix-1.c new file mode 100644 index 00000000000..f4e0c7ffa1f --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-intermix-1.c @@ -0,0 +1,13 @@ +/* { dg-options "-mips16 -mabi=32" } */ + +__attribute__((nomips16, always_inline)) +inline int foo() /* { dg-error "target specific option mismatch" } */ +{ + return 1; +} + +int bar() +{ + return foo(); +} + diff --git a/gcc/testsuite/gcc.target/mips/inline-intermix-2.c b/gcc/testsuite/gcc.target/mips/inline-intermix-2.c new file mode 100644 index 00000000000..c0b0102941d --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-intermix-2.c @@ -0,0 +1,13 @@ +/* { dg-options "-mips16 -mabi=32" } */ + +__attribute__((nomips16, always_inline, inline_intermix)) +inline int foo() +{ + return 1; +} + +int bar() +{ + return foo(); +} + diff --git a/gcc/testsuite/gcc.target/mips/inline-intermix-3.c b/gcc/testsuite/gcc.target/mips/inline-intermix-3.c new file mode 100644 index 00000000000..bc947315fb8 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-intermix-3.c @@ -0,0 +1,13 @@ +/* { dg-options "-mips16 -mabi=32 -minline-intermix" } */ + +__attribute__((nomips16, always_inline)) +inline int foo() +{ + return 1; +} + +int bar() +{ + return foo(); +} + diff --git a/gcc/testsuite/gcc.target/mips/inline-intermix-4.c b/gcc/testsuite/gcc.target/mips/inline-intermix-4.c new file mode 100644 index 00000000000..8c58284b477 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-intermix-4.c @@ -0,0 +1,13 @@ +/* { dg-options "-mips16 -mabi=32 -minline-intermix" } */ + +__attribute__((nomips16, always_inline, inline_intermix("no"))) +inline int foo() /* { dg-error "target specific option mismatch" } */ +{ + return 1; +} + +int bar() +{ + return foo(); +} + diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp index 3907fe2a778..dade793b306 100644 --- a/gcc/testsuite/gcc.target/mips/mips.exp +++ b/gcc/testsuite/gcc.target/mips/mips.exp @@ -285,6 +285,7 @@ foreach option { fix-r10000 fix-vr4130 gpopt + inline-intermix local-sdata long-calls lxc1-sxc1 -- 2.34.1