On 2/7/22 09:11, Jakub Jelinek wrote:
...
> 1) formatting, = should be at the start of next line rather than end of the
>    line
> 2) all_masks, always_inline_safe_masks and caller_required_masks aren't
>    ever modified, perhaps make them const?
> 3) I wonder if there is any advantage to have all_masks with all the masks
>    enumerated, compared to
>    const HOST_WIDE_INT all_masks
>      = (caller_required_masks | must_match_masks | always_inline_safe_masks
>       | MASK_DEBUG_ARG | MASK_PACKED_STACK | MASK_ZVECTOR);
>    i.e. when you add a new mask, instead of listing it in all_masks
>    and one or more of the other vars you'd just stick it either in one
>    or more of those vars or in all_masks.

I've just committed the patch with these changes. Thanks Jakub!

Andreas


diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 5c2a830f9f0..c6cfe41ad7b 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 00000000000..d54e5d58cc4
--- /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);
+}
-- 
2.34.1

Reply via email to