aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/s390/s390.cc64
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr104327.c15
2 files changed, 62 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
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr104327.c b/gcc/testsuite/gcc.c-torture/compile/pr104327.c
new file mode 100644
index 0000000..d54e5d5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr104327.c
@@ -0,0 +1,15 @@
+/* PR target/104327 */
+
+void foo (int *);
+
+static inline __attribute__((always_inline)) void
+bar (int *x)
+{
+ foo (x);
+}
+
+__attribute__((cold, optimize("Os"))) void
+baz (int *x)
+{
+ bar (x);
+}