aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@linux.ibm.com>2022-02-06 09:07:41 +0100
committerAndreas Krebbel <krebbel@linux.ibm.com>2022-02-07 11:18:08 +0100
commitdb95441cf5399aabc46ca83df19f7290c3e23cb1 (patch)
tree7ec67943839220c0e91d7c2f8b8efc4873e47ea0 /gcc/config/s390
parent70430001b74d0f67386a6b3642c857b3389cd5d0 (diff)
downloadgcc-db95441cf5399aabc46ca83df19f7290c3e23cb1.zip
gcc-db95441cf5399aabc46ca83df19f7290c3e23cb1.tar.gz
gcc-db95441cf5399aabc46ca83df19f7290c3e23cb1.tar.bz2
Check always_inline flag in s390_can_inline_p [PR104327]
MASK_MVCLE is set for -Os but not for other optimization levels. In general it should not make much sense to inline across calls where the flag is different but we have to allow it for always_inline. The patch also rearranges the hook implementation a bit based on the recommendations from Jakub und Martin in the PR. Bootstrapped and regression tested on s390x with various arch flags. Will commit after giving a few days for comments. gcc/ChangeLog: PR target/104327 * config/s390/s390.cc (s390_can_inline_p): Accept a few more flags if always_inline is set. Don't inline when tune differs without always_inline. gcc/testsuite/ChangeLog: PR target/104327 * gcc.c-torture/compile/pr104327.c: New test.
Diffstat (limited to 'gcc/config/s390')
-rw-r--r--gcc/config/s390/s390.cc64
1 files changed, 47 insertions, 17 deletions
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 5c2a830..c6cfe41 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -16091,6 +16091,23 @@ s390_valid_target_attribute_p (tree fndecl,
static bool
s390_can_inline_p (tree caller, tree callee)
{
+ /* Flags which if present in the callee are required in the caller as well. */
+ const unsigned HOST_WIDE_INT caller_required_masks = MASK_OPT_HTM;
+
+ /* Flags which affect the ABI and in general prevent inlining. */
+ unsigned HOST_WIDE_INT must_match_masks
+ = (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP | MASK_SOFT_FLOAT
+ | MASK_LONG_DOUBLE_128 | MASK_OPT_VX);
+
+ /* Flags which we in general want to prevent inlining but accept for
+ always_inline. */
+ const unsigned HOST_WIDE_INT always_inline_safe_masks
+ = MASK_MVCLE | MASK_BACKCHAIN | MASK_SMALL_EXEC;
+
+ const HOST_WIDE_INT all_masks
+ = (caller_required_masks | must_match_masks | always_inline_safe_masks
+ | MASK_DEBUG_ARG | MASK_PACKED_STACK | MASK_ZVECTOR);
+
tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
@@ -16103,16 +16120,18 @@ s390_can_inline_p (tree caller, tree callee)
struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
- bool ret = true;
- if ((caller_opts->x_target_flags & ~(MASK_SOFT_FLOAT | MASK_HARD_DFP))
- != (callee_opts->x_target_flags & ~(MASK_SOFT_FLOAT | MASK_HARD_DFP)))
- ret = false;
+ /* If one of these triggers make sure to add proper handling of your
+ new flag to this hook. */
+ gcc_assert (!(caller_opts->x_target_flags & ~all_masks));
+ gcc_assert (!(callee_opts->x_target_flags & ~all_masks));
- /* Don't inline functions to be compiled for a more recent arch into a
- function for an older arch. */
- else if (caller_opts->x_s390_arch < callee_opts->x_s390_arch)
- ret = false;
+ bool always_inline
+ = (DECL_DISREGARD_INLINE_LIMITS (callee)
+ && lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee)));
+
+ if (!always_inline)
+ must_match_masks |= always_inline_safe_masks;
/* Inlining a hard float function into a soft float function is only
allowed if the hard float function doesn't actually make use of
@@ -16120,16 +16139,27 @@ s390_can_inline_p (tree caller, tree callee)
We are called from FEs for multi-versioning call optimization, so
beware of ipa_fn_summaries not available. */
- else if (((TARGET_SOFT_FLOAT_P (caller_opts->x_target_flags)
- && !TARGET_SOFT_FLOAT_P (callee_opts->x_target_flags))
- || (!TARGET_HARD_DFP_P (caller_opts->x_target_flags)
- && TARGET_HARD_DFP_P (callee_opts->x_target_flags)))
- && (! ipa_fn_summaries
- || ipa_fn_summaries->get
- (cgraph_node::get (callee))->fp_expressions))
- ret = false;
+ if (always_inline && ipa_fn_summaries
+ && !ipa_fn_summaries->get(cgraph_node::get (callee))->fp_expressions)
+ must_match_masks &= ~(MASK_HARD_DFP | MASK_SOFT_FLOAT);
- return ret;
+ if ((caller_opts->x_target_flags & must_match_masks)
+ != (callee_opts->x_target_flags & must_match_masks))
+ return false;
+
+ if (~(caller_opts->x_target_flags & caller_required_masks)
+ & (callee_opts->x_target_flags & caller_required_masks))
+ return false;
+
+ /* Don't inline functions to be compiled for a more recent arch into a
+ function for an older arch. */
+ if (caller_opts->x_s390_arch < callee_opts->x_s390_arch)
+ return false;
+
+ if (!always_inline && caller_opts->x_s390_tune != callee_opts->x_s390_tune)
+ return false;
+
+ return true;
}
#endif