diff mbox series

rs6000: Fix some issues in rs6000_can_inline_p [PR102059]

Message ID 3f2c6df2-e458-483c-facd-148a3cc3aead@linux.ibm.com
State New
Headers show
Series rs6000: Fix some issues in rs6000_can_inline_p [PR102059] | expand

Commit Message

Kewen.Lin Sept. 1, 2021, 6:55 a.m. UTC
Hi!

This patch is to fix the inconsistent behaviors for non-LTO mode
and LTO mode.  As Martin pointed out, currently the function
rs6000_can_inline_p simply makes it inlinable if callee_tree is
NULL, but it's wrong, we should use the command line options
from target_option_default_node as default.  It also replaces
rs6000_isa_flags with the one from target_option_default_node
when caller_tree is NULL as rs6000_isa_flags could probably
change since initialization.

It also extends the scope of the check for the case that callee
has explicit set options, for test case pr102059-2.c inlining can
happen unexpectedly before, it's fixed accordingly.

As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
can be neglected for inlining, this patch also exludes them when
the callee is attributed by always_inline.

Bootstrapped and regtested on powerpc64le-linux-gnu Power9.

BR,
Kewen
-----
gcc/ChangeLog:

	PR ipa/102059
	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
	target_option_default_node and consider always_inline_safe flags.

gcc/testsuite/ChangeLog:

	PR ipa/102059
	* gcc.target/powerpc/pr102059-1.c: New test.
	* gcc.target/powerpc/pr102059-2.c: New test.
	* gcc.target/powerpc/pr102059-3.c: New test.
	* gcc.target/powerpc/pr102059-4.c: New test.
---
 gcc/config/rs6000/rs6000.c                    | 87 +++++++++++------
 gcc/testsuite/gcc.target/powerpc/pr102059-1.c | 24 +++++
 gcc/testsuite/gcc.target/powerpc/pr102059-2.c | 20 ++++
 gcc/testsuite/gcc.target/powerpc/pr102059-3.c | 95 +++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/pr102059-4.c | 22 +++++
 5 files changed, 221 insertions(+), 27 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr102059-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr102059-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr102059-3.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr102059-4.c

Comments

Kewen.Lin Sept. 15, 2021, 8:42 a.m. UTC | #1
Hi!

Gentle ping this patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html

BR,
Kewen

on 2021/9/1 下午2:55, Kewen.Lin via Gcc-patches wrote:
> Hi!
> 
> This patch is to fix the inconsistent behaviors for non-LTO mode
> and LTO mode.  As Martin pointed out, currently the function
> rs6000_can_inline_p simply makes it inlinable if callee_tree is
> NULL, but it's wrong, we should use the command line options
> from target_option_default_node as default.  It also replaces
> rs6000_isa_flags with the one from target_option_default_node
> when caller_tree is NULL as rs6000_isa_flags could probably
> change since initialization.
> 
> It also extends the scope of the check for the case that callee
> has explicit set options, for test case pr102059-2.c inlining can
> happen unexpectedly before, it's fixed accordingly.
> 
> As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
> can be neglected for inlining, this patch also exludes them when
> the callee is attributed by always_inline.
> 
> Bootstrapped and regtested on powerpc64le-linux-gnu Power9.
> 
> BR,
> Kewen
> -----
> gcc/ChangeLog:
> 
> 	PR ipa/102059
> 	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
> 	target_option_default_node and consider always_inline_safe flags.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR ipa/102059
> 	* gcc.target/powerpc/pr102059-1.c: New test.
> 	* gcc.target/powerpc/pr102059-2.c: New test.
> 	* gcc.target/powerpc/pr102059-3.c: New test.
> 	* gcc.target/powerpc/pr102059-4.c: New test.
>
Kewen.Lin Sept. 28, 2021, 8:58 a.m. UTC | #2
Hi,

Gentle ping this patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html

One related patch [1] is ready to commit, whose test cases rely on
this patch if no changes are applied to them.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579658.html

BR,
Kewen

on 2021/9/15 下午4:42, Kewen.Lin via Gcc-patches wrote:
> Hi!
> 
> Gentle ping this patch:
> 
> https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html
> 
> BR,
> Kewen
> 
> on 2021/9/1 下午2:55, Kewen.Lin via Gcc-patches wrote:
>> Hi!
>>
>> This patch is to fix the inconsistent behaviors for non-LTO mode
>> and LTO mode.  As Martin pointed out, currently the function
>> rs6000_can_inline_p simply makes it inlinable if callee_tree is
>> NULL, but it's wrong, we should use the command line options
>> from target_option_default_node as default.  It also replaces
>> rs6000_isa_flags with the one from target_option_default_node
>> when caller_tree is NULL as rs6000_isa_flags could probably
>> change since initialization.
>>
>> It also extends the scope of the check for the case that callee
>> has explicit set options, for test case pr102059-2.c inlining can
>> happen unexpectedly before, it's fixed accordingly.
>>
>> As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
>> can be neglected for inlining, this patch also exludes them when
>> the callee is attributed by always_inline.
>>
>> Bootstrapped and regtested on powerpc64le-linux-gnu Power9.
>>
>> BR,
>> Kewen
>> -----
>> gcc/ChangeLog:
>>
>> 	PR ipa/102059
>> 	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
>> 	target_option_default_node and consider always_inline_safe flags.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	PR ipa/102059
>> 	* gcc.target/powerpc/pr102059-1.c: New test.
>> 	* gcc.target/powerpc/pr102059-2.c: New test.
>> 	* gcc.target/powerpc/pr102059-3.c: New test.
>> 	* gcc.target/powerpc/pr102059-4.c: New test.
>>
>
Kewen.Lin Oct. 13, 2021, 2:33 a.m. UTC | #3
Hi,

Gentle ping this patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html

One related patch [1] is ready to commit, whose test cases rely on
this patch if no changes are applied to them.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579658.html

BR,
Kewen

>> on 2021/9/1 下午2:55, Kewen.Lin via Gcc-patches wrote:
>>> Hi!
>>>
>>> This patch is to fix the inconsistent behaviors for non-LTO mode
>>> and LTO mode.  As Martin pointed out, currently the function
>>> rs6000_can_inline_p simply makes it inlinable if callee_tree is
>>> NULL, but it's wrong, we should use the command line options
>>> from target_option_default_node as default.  It also replaces
>>> rs6000_isa_flags with the one from target_option_default_node
>>> when caller_tree is NULL as rs6000_isa_flags could probably
>>> change since initialization.
>>>
>>> It also extends the scope of the check for the case that callee
>>> has explicit set options, for test case pr102059-2.c inlining can
>>> happen unexpectedly before, it's fixed accordingly.
>>>
>>> As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
>>> can be neglected for inlining, this patch also exludes them when
>>> the callee is attributed by always_inline.
>>>
>>> Bootstrapped and regtested on powerpc64le-linux-gnu Power9.
>>>
>>> BR,
>>> Kewen
>>> -----
>>> gcc/ChangeLog:
>>>
>>> 	PR ipa/102059
>>> 	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
>>> 	target_option_default_node and consider always_inline_safe flags.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 	PR ipa/102059
>>> 	* gcc.target/powerpc/pr102059-1.c: New test.
>>> 	* gcc.target/powerpc/pr102059-2.c: New test.
>>> 	* gcc.target/powerpc/pr102059-3.c: New test.
>>> 	* gcc.target/powerpc/pr102059-4.c: New test.
>>>
>>
Kewen.Lin Oct. 20, 2021, 9:30 a.m. UTC | #4
Hi,

Gentle ping this patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html

One related patch [1] is ready to commit, whose test cases rely on
this patch if no changes are applied to them.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579658.html

BR,
Kewen

>>> on 2021/9/1 下午2:55, Kewen.Lin via Gcc-patches wrote:
>>>> Hi!
>>>>
>>>> This patch is to fix the inconsistent behaviors for non-LTO mode
>>>> and LTO mode.  As Martin pointed out, currently the function
>>>> rs6000_can_inline_p simply makes it inlinable if callee_tree is
>>>> NULL, but it's wrong, we should use the command line options
>>>> from target_option_default_node as default.  It also replaces
>>>> rs6000_isa_flags with the one from target_option_default_node
>>>> when caller_tree is NULL as rs6000_isa_flags could probably
>>>> change since initialization.
>>>>
>>>> It also extends the scope of the check for the case that callee
>>>> has explicit set options, for test case pr102059-2.c inlining can
>>>> happen unexpectedly before, it's fixed accordingly.
>>>>
>>>> As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
>>>> can be neglected for inlining, this patch also exludes them when
>>>> the callee is attributed by always_inline.
>>>>
>>>> Bootstrapped and regtested on powerpc64le-linux-gnu Power9.
>>>>
>>>> BR,
>>>> Kewen
>>>> -----
>>>> gcc/ChangeLog:
>>>>
>>>> 	PR ipa/102059
>>>> 	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
>>>> 	target_option_default_node and consider always_inline_safe flags.
>>>>
>>>> gcc/testsuite/ChangeLog:
>>>>
>>>> 	PR ipa/102059
>>>> 	* gcc.target/powerpc/pr102059-1.c: New test.
>>>> 	* gcc.target/powerpc/pr102059-2.c: New test.
>>>> 	* gcc.target/powerpc/pr102059-3.c: New test.
>>>> 	* gcc.target/powerpc/pr102059-4.c: New test.
>>>>
>>>
Kewen.Lin Nov. 4, 2021, 10:57 a.m. UTC | #5
Hi,

Gentle ping this patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html

One related patch [1] is ready to commit, whose test cases rely on
this patch if no changes are applied to them.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579658.html

BR,
Kewen

>>>> on 2021/9/1 下午2:55, Kewen.Lin via Gcc-patches wrote:
>>>>> Hi!
>>>>>
>>>>> This patch is to fix the inconsistent behaviors for non-LTO mode
>>>>> and LTO mode.  As Martin pointed out, currently the function
>>>>> rs6000_can_inline_p simply makes it inlinable if callee_tree is
>>>>> NULL, but it's wrong, we should use the command line options
>>>>> from target_option_default_node as default.  It also replaces
>>>>> rs6000_isa_flags with the one from target_option_default_node
>>>>> when caller_tree is NULL as rs6000_isa_flags could probably
>>>>> change since initialization.
>>>>>
>>>>> It also extends the scope of the check for the case that callee
>>>>> has explicit set options, for test case pr102059-2.c inlining can
>>>>> happen unexpectedly before, it's fixed accordingly.
>>>>>
>>>>> As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
>>>>> can be neglected for inlining, this patch also exludes them when
>>>>> the callee is attributed by always_inline.
>>>>>
>>>>> Bootstrapped and regtested on powerpc64le-linux-gnu Power9.
>>>>>
>>>>> BR,
>>>>> Kewen
>>>>> -----
>>>>> gcc/ChangeLog:
>>>>>
>>>>> 	PR ipa/102059
>>>>> 	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
>>>>> 	target_option_default_node and consider always_inline_safe flags.
>>>>>
>>>>> gcc/testsuite/ChangeLog:
>>>>>
>>>>> 	PR ipa/102059
>>>>> 	* gcc.target/powerpc/pr102059-1.c: New test.
>>>>> 	* gcc.target/powerpc/pr102059-2.c: New test.
>>>>> 	* gcc.target/powerpc/pr102059-3.c: New test.
>>>>> 	* gcc.target/powerpc/pr102059-4.c: New test.
>>>>>
>>>>
Kewen.Lin Nov. 22, 2021, 2:24 a.m. UTC | #6
Hi,

Gentle ping this patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578552.html

One related patch [1] is ready to commit, whose test cases rely on
this patch if no changes are applied to them.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579658.html

BR,
Kewen

>>>>> on 2021/9/1 下午2:55, Kewen.Lin via Gcc-patches wrote:
>>>>>> Hi!
>>>>>>
>>>>>> This patch is to fix the inconsistent behaviors for non-LTO mode
>>>>>> and LTO mode.  As Martin pointed out, currently the function
>>>>>> rs6000_can_inline_p simply makes it inlinable if callee_tree is
>>>>>> NULL, but it's wrong, we should use the command line options
>>>>>> from target_option_default_node as default.  It also replaces
>>>>>> rs6000_isa_flags with the one from target_option_default_node
>>>>>> when caller_tree is NULL as rs6000_isa_flags could probably
>>>>>> change since initialization.
>>>>>>
>>>>>> It also extends the scope of the check for the case that callee
>>>>>> has explicit set options, for test case pr102059-2.c inlining can
>>>>>> happen unexpectedly before, it's fixed accordingly.
>>>>>>
>>>>>> As Richi/Mike pointed out, some tuning flags like MASK_P8_FUSION
>>>>>> can be neglected for inlining, this patch also exludes them when
>>>>>> the callee is attributed by always_inline.
>>>>>>
>>>>>> Bootstrapped and regtested on powerpc64le-linux-gnu Power9.
>>>>>>
>>>>>> BR,
>>>>>> Kewen
>>>>>> -----
>>>>>> gcc/ChangeLog:
>>>>>>
>>>>>> 	PR ipa/102059
>>>>>> 	* config/rs6000/rs6000.c (rs6000_can_inline_p): Adjust with
>>>>>> 	target_option_default_node and consider always_inline_safe flags.
>>>>>>
>>>>>> gcc/testsuite/ChangeLog:
>>>>>>
>>>>>> 	PR ipa/102059
>>>>>> 	* gcc.target/powerpc/pr102059-1.c: New test.
>>>>>> 	* gcc.target/powerpc/pr102059-2.c: New test.
>>>>>> 	* gcc.target/powerpc/pr102059-3.c: New test.
>>>>>> 	* gcc.target/powerpc/pr102059-4.c: New test.
>>>>>>
>>>>>
Segher Boessenkool Nov. 29, 2021, 4:57 p.m. UTC | #7
Hi!

On Wed, Sep 01, 2021 at 02:55:51PM +0800, Kewen.Lin wrote:
> This patch is to fix the inconsistent behaviors for non-LTO mode
> and LTO mode.  As Martin pointed out, currently the function
> rs6000_can_inline_p simply makes it inlinable if callee_tree is
> NULL, but it's wrong, we should use the command line options
> from target_option_default_node as default.

This is not documented.

> It also replaces
> rs6000_isa_flags with the one from target_option_default_node
> when caller_tree is NULL as rs6000_isa_flags could probably
> change since initialization.

Is this enough then?  Are there no other places that use
rs6000_isa_flags?  Is it correct for us to have that variable at all
anymore?  Etc.

> +  bool always_inline =
> +    (DECL_DISREGARD_INLINE_LIMITS (callee)
> +     && lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee)));

The "=" should start a line, not end it.  And please don't use
unnecessary parens.

> +  /* Some flags such as fusion can be tolerated for always inlines.  */
> +  unsigned HOST_WIDE_INT always_inline_safe_mask =
> +    (MASK_P8_FUSION | MASK_P10_FUSION | OPTION_MASK_SAVE_TOC_INDIRECT
> +     | OPTION_MASK_P8_FUSION_SIGN | OPTION_MASK_P10_FUSION_LD_CMPI
> +     | OPTION_MASK_P10_FUSION_2LOGICAL | OPTION_MASK_P10_FUSION_LOGADD
> +     | OPTION_MASK_P10_FUSION_ADDLOG | OPTION_MASK_P10_FUSION_2ADD
> +     | OPTION_MASK_PCREL_OPT);

Same.

The fusion ones are obvious.  The other two are not.  Please put those
two more obviously separate (not somewhere in the sea of fusion
options), and some comment wouldn't hurt either.  You can make it
separate statements even, make it really stand out.

Why are there OPTION_MASKs for separate P10 fusion types here, as well as
MASK_P10_FUSION?

> +
> +  if (always_inline) {
> +    caller_isa &= ~always_inline_safe_mask;
> +    callee_isa &= ~always_inline_safe_mask;
> +  }

"{" starts a new line, indented.


Segher
Michael Meissner Dec. 3, 2021, 12:51 a.m. UTC | #8
On Mon, Nov 29, 2021 at 10:57:12AM -0600, Segher Boessenkool wrote:
> Why are there OPTION_MASKs for separate P10 fusion types here, as well as
> MASK_P10_FUSION?

Well going back in time, before we used rs6000_isa_flags, we used the default
flag word for MASK arguments.  Unfortunately, the default flag word is only
32-bits, and we needed more mask bits, so we moved to rs6000_isa_flags, which
is HOST_WIDE_INT.

Unfortunately, the options infrastructure used 'OPTION_MASK_<foo>' instead of
'MASK_<foo>'.  So we have a bunch of macros in rs6000.h that map 'MASK_<foo>'
to 'OPTION_MASK_<foo>'.

We should clean this up and use 'OPTION_MASK_<foo>' everywhere, but so far it
hasn't percolated to the top as being important enough to do.

As new options are added, people just clone the code and add new macros, even
though in theory nobody should be using MASK_P10_FUSION_<foo>.
Kewen.Lin Dec. 3, 2021, 3:30 a.m. UTC | #9
Hi Mike,

on 2021/12/3 上午8:51, Michael Meissner wrote:
> On Mon, Nov 29, 2021 at 10:57:12AM -0600, Segher Boessenkool wrote:
>> Why are there OPTION_MASKs for separate P10 fusion types here, as well as
>> MASK_P10_FUSION?
> 
> Well going back in time, before we used rs6000_isa_flags, we used the default
> flag word for MASK arguments.  Unfortunately, the default flag word is only
> 32-bits, and we needed more mask bits, so we moved to rs6000_isa_flags, which
> is HOST_WIDE_INT.
> 
> Unfortunately, the options infrastructure used 'OPTION_MASK_<foo>' instead of
> 'MASK_<foo>'.  So we have a bunch of macros in rs6000.h that map 'MASK_<foo>'
> to 'OPTION_MASK_<foo>'.
> 
> We should clean this up and use 'OPTION_MASK_<foo>' everywhere, but so far it
> hasn't percolated to the top as being important enough to do.
> 
> As new options are added, people just clone the code and add new macros, even
> though in theory nobody should be using MASK_P10_FUSION_<foo>.
> 

Thanks for the explanation on the history.  Fortunately now for Power10 fusion,
we have only one defined MASK_P10_FUSION but not the other MASK_P10_FUSION_<...>.

As you explained, I will use OPTION_MASK_P10_FUSION and OPTION_MASK_P8_FUSION
instead.

BR,
Kewen
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 46b8909104e..c2582a3efab 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -25058,45 +25058,78 @@  rs6000_generate_version_dispatcher_body (void *node_p)
 static bool
 rs6000_can_inline_p (tree caller, tree callee)
 {
-  bool ret = false;
   tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
   tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
 
-  /* If the callee has no option attributes, then it is ok to inline.  */
+  /* If the caller/callee has option attributes, then use them.
+     Otherwise, use the command line options.  */
   if (!callee_tree)
-    ret = true;
+    callee_tree = target_option_default_node;
+  if (!caller_tree)
+    caller_tree = target_option_default_node;
+
+  struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
+  struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
+  HOST_WIDE_INT caller_isa = caller_opts->x_rs6000_isa_flags;
+  HOST_WIDE_INT callee_isa = callee_opts->x_rs6000_isa_flags;
+
+  bool always_inline =
+    (DECL_DISREGARD_INLINE_LIMITS (callee)
+     && lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee)));
+
+  /* Some flags such as fusion can be tolerated for always inlines.  */
+  unsigned HOST_WIDE_INT always_inline_safe_mask =
+    (MASK_P8_FUSION | MASK_P10_FUSION | OPTION_MASK_SAVE_TOC_INDIRECT
+     | OPTION_MASK_P8_FUSION_SIGN | OPTION_MASK_P10_FUSION_LD_CMPI
+     | OPTION_MASK_P10_FUSION_2LOGICAL | OPTION_MASK_P10_FUSION_LOGADD
+     | OPTION_MASK_P10_FUSION_ADDLOG | OPTION_MASK_P10_FUSION_2ADD
+     | OPTION_MASK_PCREL_OPT);
+
+  if (always_inline) {
+    caller_isa &= ~always_inline_safe_mask;
+    callee_isa &= ~always_inline_safe_mask;
+  }
 
-  else
+  /* The callee's options must be a subset of the caller's options, i.e.
+     a vsx function may inline an altivec function, but a no-vsx function
+     must not inline a vsx function.  */
+  if ((caller_isa & callee_isa) != callee_isa)
     {
-      HOST_WIDE_INT caller_isa;
-      struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
-      HOST_WIDE_INT callee_isa = callee_opts->x_rs6000_isa_flags;
-      HOST_WIDE_INT explicit_isa = callee_opts->x_rs6000_isa_flags_explicit;
-
-      /* If the caller has option attributes, then use them.
-	 Otherwise, use the command line options.  */
-      if (caller_tree)
-	caller_isa = TREE_TARGET_OPTION (caller_tree)->x_rs6000_isa_flags;
-      else
-	caller_isa = rs6000_isa_flags;
+      if (TARGET_DEBUG_TARGET)
+	fprintf (stderr,
+		 "rs6000_can_inline_p:, caller %s, callee %s, cannot "
+		 "inline since callee's options set isn't a subset of "
+		 "caller's options set.\n",
+		 get_decl_name (caller), get_decl_name (callee));
+      return false;
+    }
 
-      /* The callee's options must be a subset of the caller's options, i.e.
-	 a vsx function may inline an altivec function, but a no-vsx function
-	 must not inline a vsx function.  However, for those options that the
-	 callee has explicitly enabled or disabled, then we must enforce that
-	 the callee's and caller's options match exactly; see PR70010.  */
-      if (((caller_isa & callee_isa) == callee_isa)
-	  && (caller_isa & explicit_isa) == (callee_isa & explicit_isa))
-	ret = true;
+  /* For those options that the callee has explicitly enabled or disabled,
+     then we must enforce that the callee's and caller's options match
+     exactly; see PR70010.  */
+  HOST_WIDE_INT explicit_isa = callee_opts->x_rs6000_isa_flags_explicit;
+  if (always_inline)
+    explicit_isa &= ~always_inline_safe_mask;
+  if ((caller_isa & explicit_isa) != (callee_isa & explicit_isa))
+    {
+      if (TARGET_DEBUG_TARGET)
+	fprintf (stderr,
+		 "rs6000_can_inline_p:, caller %s, callee %s, cannot "
+		 "inline since callee's options set isn't a subset of "
+		 "caller's options set by considering callee's "
+		 "explicitly set options.\n",
+		 get_decl_name (caller), get_decl_name (callee));
+      return false;
     }
 
   if (TARGET_DEBUG_TARGET)
-    fprintf (stderr, "rs6000_can_inline_p:, caller %s, callee %s, %s inline\n",
-	     get_decl_name (caller), get_decl_name (callee),
-	     (ret ? "can" : "cannot"));
+    fprintf (stderr,
+	     "rs6000_can_inline_p:, caller %s, callee %s, can inline.\n",
+	     get_decl_name (caller), get_decl_name (callee));
 
-  return ret;
+  return true;
 }
+
 
 /* Allocate a stack temp and fixup the address so it meets the particular
    memory requirements (either offetable or REG+REG addressing).  */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr102059-1.c b/gcc/testsuite/gcc.target/powerpc/pr102059-1.c
new file mode 100644
index 00000000000..d2a002cf141
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr102059-1.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power8" } */
+
+/* Verify it emits inlining error msg at non-LTO mode.  */
+
+#include <htmintrin.h>
+
+static inline int __attribute__ ((always_inline))
+foo (int *b) /* { dg-error "inlining failed in call to .* target specific option mismatch" } */
+{
+  int res = _HTM_STATE(__builtin_ttest());
+  *b += res;
+  return *b;
+}
+
+#pragma GCC target "cpu=power10"
+int
+bar (int *a)
+{
+  *a = foo (a); /* { dg-message "called from here" } */
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr102059-2.c b/gcc/testsuite/gcc.target/powerpc/pr102059-2.c
new file mode 100644
index 00000000000..1d5d6c38bf3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr102059-2.c
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-vsx" } */
+
+/* Verify it emits inlining error msg when the callee has explicit
+   disabling option from command line.  */
+
+vector int c, a, b;
+
+static inline void __attribute__ ((__always_inline__))
+foo () /* { dg-error "inlining failed in call to .* target specific option mismatch" } */
+{
+  c = a + b;
+}
+
+__attribute__ ((target ("vsx")))
+int main ()
+{
+  foo (); /* { dg-message "called from here" } */
+  c = a + b;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr102059-3.c b/gcc/testsuite/gcc.target/powerpc/pr102059-3.c
new file mode 100644
index 00000000000..9684cab986a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr102059-3.c
@@ -0,0 +1,95 @@ 
+/* { dg-do compile } */
+/* -Wno-attributes suppresses always_inline warnings.  */
+/* { dg-options "-O2 -mdejagnu-cpu=power8 -Wno-attributes" } */
+
+/* Verify it doesn't emit inlining error msg since some mismatched
+   features are considered as safe for always_inline.  */
+
+/* 1. Callee enables Power8 fusion implicitly, while caller
+      with Power9 doesn't support power8 fusion at all.  */
+
+__attribute__ ((always_inline))
+int callee1 (int *b)
+{
+  *b += 1;
+  return *b;
+}
+
+#pragma GCC target "cpu=power9"
+int caller1 (int *a)
+{
+  *a = callee1 (a);
+  return 0;
+}
+
+/* 2. Caller enables indirect toc save feature while callee
+      disables it explicitly.  */
+
+#pragma GCC target "save-toc-indirect"
+__attribute__ ((always_inline))
+int callee2 (int *b)
+{
+  *b += 2;
+  return *b;
+}
+
+#pragma GCC target "no-save-toc-indirect"
+int caller2 (int *a)
+{
+  *a = callee2 (a);
+  return 0;
+}
+
+/* 3. Caller disables Power10 fusion explicitly, while callee
+      still supports it as Power10 turns it on by default.  */
+
+#pragma GCC target "cpu=power10"
+__attribute__ ((always_inline))
+int callee3 (int *b)
+{
+  *b += 3;
+  return *b;
+}
+
+#pragma GCC target "cpu=power10,no-power10-fusion"
+int caller3 (int *a)
+{
+  *a = callee3 (a);
+  return 0;
+}
+
+/* 4. Caller enables Power10 fusion implicitly, while callee
+      disables it explicitly.  */
+
+#pragma GCC target "no-power10-fusion"
+__attribute__ ((always_inline))
+int callee4 (int *b)
+{
+  *b += 4;
+  return *b;
+}
+
+#pragma GCC target "cpu=power10"
+int caller4 (int *a)
+{
+  *a = callee4 (a);
+  return 0;
+}
+
+/* 5. Caller disables pcrel-opt while callee enables it explicitly.  */
+
+#pragma GCC target "cpu=power10,no-pcrel-opt"
+__attribute__ ((always_inline))
+int callee5 (int *b)
+{
+  *b += 5;
+  return *b;
+}
+
+#pragma GCC target "cpu=power10,pcrel-opt"
+int caller5 (int *a)
+{
+  *a = callee5 (a);
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr102059-4.c b/gcc/testsuite/gcc.target/powerpc/pr102059-4.c
new file mode 100644
index 00000000000..0f27f2ce7d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr102059-4.c
@@ -0,0 +1,22 @@ 
+/* { dg-do compile } */
+/* -Wno-attributes suppresses always_inline warnings.  */
+/* { dg-options "-O2 -mdejagnu-cpu=power8 -mno-power8-fusion -Wno-attributes" } */
+
+/* Verify it doesn't emit inlining error msg since the flag power8
+   fusion is considered as safe for always_inline, it's still safe
+   even the flag is set explicitly.  */
+
+__attribute__ ((always_inline))
+int foo (int *b)
+{
+  *b += 10;
+  return *b;
+}
+
+#pragma GCC target "power8-fusion"
+int bar (int *a)
+{
+  *a = foo (a);
+  return 0;
+}
+