diff mbox series

[1/9] Add rs6000 architecture masks.

Message ID Zqx21hUTwx6FIlkR@cowardly-lion.the-meissners.org
State New
Headers show
Series Adding PowerPC architecture flags in addition to ISA flags | expand

Commit Message

Michael Meissner Aug. 2, 2024, 6:04 a.m. UTC
This patch begins the journey to move architecture bits that are not user ISA
options from rs6000_isa_flags to a new targt variable rs6000_arch_flags.  The
intention is to remove switches that are currently isa options, but the user
should not be using this particular option. For example, we want users to use
-mcpu=power10 and not just -mpower10.

This patch also changes the target_clones support to use an architecture mask
instead of isa bits.

This patch also switches the handling of .machine to use architecture masks if
they exist (power4 through power11).  All of the other PowerPCs will continue to
use the existing code for setting the .machine option.

I have built both big endian and little endian bootstrap compilers and there
were no regressions.

In addition, I constructed a test case that used every archiecture define (like
_ARCH_PWR4, etc.) and I also looked at the .machine directive generated.  I ran
this test for all supported combinations of -mcpu, big/little endian, and 32/64
bit support.  Every single instance generated exactly the same code with the
patches installed compared to the compiler before installing the patches.

Can I install this patch on the GCC 15 trunk?

2024-08-01  Michael Meissner  <meissner@linux.ibm.com>

gcc/

	* config/rs6000/rs6000-arch.def: New file.
	* config/rs6000/rs6000.cc (struct clone_map): Switch to using
	architecture masks instead of ISA masks.
	(rs6000_clone_map): Likewise.
	(rs6000_print_isa_options): Add an architecture flags argument, change
	all callers.
	(get_arch_flag): New function.
	(rs6000_debug_reg_global): Update rs6000_print_isa_options calls.
	(rs6000_option_override_internal): Likewise.
	(rs6000_machine_from_flags): Switch to using architecture masks instead
	of ISA masks.
	(struct rs6000_arch_mask): New structure.
	(rs6000_arch_masks): New table of architecutre masks and names.
	(rs6000_function_specific_save): Save architecture flags.
	(rs6000_function_specific_restore): Restore architecture flags.
	(rs6000_function_specific_print): Update rs6000_print_isa_options calls.
	(rs6000_print_options_internal): Add architecture flags options.
	(rs6000_clone_priority): Switch to using architecture masks instead of
	ISA masks.
	(rs6000_can_inline_p): Don't allow inling if the callee requires a newer
	architecture than the caller.
	* config/rs6000/rs6000.h: Use rs6000-arch.def to create the architecture
	masks.
	* config/rs6000/rs6000.opt (rs6000_arch_flags): New target variable.
	(x_rs6000_arch_flags): New save/restore field for rs6000_arch_flags.
---
 gcc/config/rs6000/rs6000-arch.def |  48 +++++++
 gcc/config/rs6000/rs6000.cc       | 215 +++++++++++++++++++++++++-----
 gcc/config/rs6000/rs6000.h        |  24 ++++
 gcc/config/rs6000/rs6000.opt      |   8 ++
 4 files changed, 259 insertions(+), 36 deletions(-)
 create mode 100644 gcc/config/rs6000/rs6000-arch.def
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000-arch.def b/gcc/config/rs6000/rs6000-arch.def
new file mode 100644
index 00000000000..e5b6e958133
--- /dev/null
+++ b/gcc/config/rs6000/rs6000-arch.def
@@ -0,0 +1,48 @@ 
+/* IBM RS/6000 CPU architecture features by processor type.
+   Copyright (C) 1991-2024 Free Software Foundation, Inc.
+   Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file defines architecture features that are based on the -mcpu=<proc>
+   option, and not on user options that can be turned on or off.  The intention
+   is for newer processors (power7 and above) to not add new ISA bits for the
+   particular processor, but add these bits.  Otherwise we have to add a bunch
+   of hidden options, just so we have the proper ISA bits.
+
+   For example, in the past we added -mpower8-internal, so that on power8,
+   power9, and power10 would inherit the option, but we had to mark the option
+   generate a warning if the user actually used it.  These options have been
+   moved from the ISA flags to the arch flags.
+
+   To use this, define the macro ARCH_EXPAND which takes 2 arguments.  The
+   first argument is the processor name in upper case, and the second argument
+   is a text name for the processor.
+
+   The function get_arch_flags when passed a processor index number will set up
+   the appropriate architecture flags based on the actual processor
+   enumeration.  */
+
+ARCH_EXPAND(POWER4,  "power4")
+ARCH_EXPAND(POWER5,  "power5")
+ARCH_EXPAND(POWER5X, "power5+")
+ARCH_EXPAND(POWER6,  "power6")
+ARCH_EXPAND(POWER7,  "power7")
+ARCH_EXPAND(POWER8,  "power8")
+ARCH_EXPAND(POWER9,  "power9")
+ARCH_EXPAND(POWER10, "power10")
+ARCH_EXPAND(POWER11, "power11")
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 0bcc6a2d0ab..bd84b880fdc 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -251,17 +251,17 @@  enum {
 
 /* Map compiler ISA bits into HWCAP names.  */
 struct clone_map {
-  HOST_WIDE_INT isa_mask;	/* rs6000_isa mask */
+  HOST_WIDE_INT arch_mask;	/* rs6000_arch_mask.  */
   const char *name;		/* name to use in __builtin_cpu_supports.  */
 };
 
 static const struct clone_map rs6000_clone_map[CLONE_MAX] = {
-  { 0,				"" },		/* Default options.  */
-  { OPTION_MASK_CMPB,		"arch_2_05" },	/* ISA 2.05 (power6).  */
-  { OPTION_MASK_POPCNTD,	"arch_2_06" },	/* ISA 2.06 (power7).  */
-  { OPTION_MASK_P8_VECTOR,	"arch_2_07" },	/* ISA 2.07 (power8).  */
-  { OPTION_MASK_P9_VECTOR,	"arch_3_00" },	/* ISA 3.0 (power9).  */
-  { OPTION_MASK_POWER10,	"arch_3_1" },	/* ISA 3.1 (power10).  */
+  { 0,			"" },		/* Default options.  */
+  { ARCH_MASK_POWER6,	"arch_2_05" },	/* ISA 2.05 (power6).  */
+  { ARCH_MASK_POWER7,	"arch_2_06" },	/* ISA 2.06 (power7).  */
+  { ARCH_MASK_POWER8,	"arch_2_07" },	/* ISA 2.07 (power8).  */
+  { ARCH_MASK_POWER9,	"arch_3_00" },	/* ISA 3.0 (power9).  */
+  { ARCH_MASK_POWER10,	"arch_3_1" },	/* ISA 3.1 (power10).  */
 };
 
 
@@ -1170,7 +1170,7 @@  enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx, enum reg_class)
 const int INSN_NOT_AVAILABLE = -1;
 
 static void rs6000_print_isa_options (FILE *, int, const char *,
-				      HOST_WIDE_INT);
+				      HOST_WIDE_INT, HOST_WIDE_INT);
 static HOST_WIDE_INT rs6000_disable_incompatible_switches (void);
 
 static enum rs6000_reg_type register_to_reg_type (rtx, bool *);
@@ -1817,6 +1817,82 @@  rs6000_cpu_name_lookup (const char *name)
   return -1;
 }
 
+
+/* Map the processor into the arch bits that are set off of -mcpu=<xxx> instead
+   of having an internal -m<foo> option.  */
+
+static HOST_WIDE_INT
+get_arch_flags (int cpu_index)
+{
+  HOST_WIDE_INT ret = 0;
+
+  const HOST_WIDE_INT ARCH_COMBO_POWER4  = ARCH_MASK_POWER4;
+  const HOST_WIDE_INT ARCH_COMBO_POWER5  = ARCH_MASK_POWER5  | ARCH_COMBO_POWER4;
+  const HOST_WIDE_INT ARCH_COMBO_POWER5X = ARCH_MASK_POWER5X | ARCH_COMBO_POWER5;
+  const HOST_WIDE_INT ARCH_COMBO_POWER6  = ARCH_MASK_POWER6  | ARCH_COMBO_POWER5X;
+  const HOST_WIDE_INT ARCH_COMBO_POWER7  = ARCH_MASK_POWER7  | ARCH_COMBO_POWER6;
+  const HOST_WIDE_INT ARCH_COMBO_POWER8  = ARCH_MASK_POWER8  | ARCH_COMBO_POWER7;
+  const HOST_WIDE_INT ARCH_COMBO_POWER9  = ARCH_MASK_POWER9  | ARCH_COMBO_POWER8;
+  const HOST_WIDE_INT ARCH_COMBO_POWER10 = ARCH_MASK_POWER10 | ARCH_COMBO_POWER9;
+  const HOST_WIDE_INT ARCH_COMBO_POWER11 = ARCH_MASK_POWER11 | ARCH_COMBO_POWER10;
+
+  if (cpu_index >= 0)
+    switch (processor_target_table[cpu_index].processor)
+      {
+      case PROCESSOR_POWER11:
+	ret = ARCH_COMBO_POWER11;
+	break;
+
+      case PROCESSOR_POWER10:
+	ret = ARCH_COMBO_POWER10;
+	break;
+
+      case PROCESSOR_POWER9:
+	ret = ARCH_COMBO_POWER9;
+	break;
+
+      case PROCESSOR_POWER8:
+	ret = ARCH_COMBO_POWER8;
+	break;
+
+      case PROCESSOR_POWER7:
+	ret = ARCH_COMBO_POWER7;
+	break;
+
+      case PROCESSOR_PPCA2:
+      case PROCESSOR_POWER6:
+	ret = ARCH_COMBO_POWER6;
+	break;
+
+      case PROCESSOR_POWER5:
+	ret = ARCH_COMBO_POWER5;
+	if (TARGET_FPRND)
+	  ret |= ARCH_MASK_POWER5X;
+	break;
+
+      case PROCESSOR_POWER4:
+	ret = ARCH_COMBO_POWER4;
+	break;
+
+      default:
+	/* For other processors, set the arch flags based on the ISA bits.  */
+	if (TARGET_MFCRF)
+	  ret |= ARCH_MASK_POWER4;
+
+	if (TARGET_POPCNTB)
+	  ret |= ARCH_MASK_POWER5;
+
+	if (TARGET_FPRND)
+	  ret |= ARCH_MASK_POWER5X;
+
+	if (TARGET_CMPB)
+	  ret |= ARCH_MASK_POWER6;
+	break;
+      }
+
+  return ret;
+}
+
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
@@ -2398,9 +2474,10 @@  rs6000_debug_reg_global (void)
       const char *name = processor_target_table[rs6000_cpu_index].name;
       HOST_WIDE_INT flags
 	= processor_target_table[rs6000_cpu_index].target_enable;
+      HOST_WIDE_INT arch_flags = get_arch_flags (rs6000_cpu_index);
 
       sprintf (flags_buffer, "-mcpu=%s flags", name);
-      rs6000_print_isa_options (stderr, 0, flags_buffer, flags);
+      rs6000_print_isa_options (stderr, 0, flags_buffer, flags, arch_flags);
     }
   else
     fprintf (stderr, DEBUG_FMT_S, "cpu", "<none>");
@@ -2410,21 +2487,26 @@  rs6000_debug_reg_global (void)
       const char *name = processor_target_table[rs6000_tune_index].name;
       HOST_WIDE_INT flags
 	= processor_target_table[rs6000_tune_index].target_enable;
+      HOST_WIDE_INT arch_flags = get_arch_flags (rs6000_tune_index);
 
       sprintf (flags_buffer, "-mtune=%s flags", name);
-      rs6000_print_isa_options (stderr, 0, flags_buffer, flags);
+      rs6000_print_isa_options (stderr, 0, flags_buffer, flags, arch_flags);
     }
   else
     fprintf (stderr, DEBUG_FMT_S, "tune", "<none>");
 
   cl_target_option_save (&cl_opts, &global_options, &global_options_set);
   rs6000_print_isa_options (stderr, 0, "rs6000_isa_flags",
-			    rs6000_isa_flags);
+			    rs6000_isa_flags, 0);
 
   rs6000_print_isa_options (stderr, 0, "rs6000_isa_flags_explicit",
-			    rs6000_isa_flags_explicit);
+			    rs6000_isa_flags_explicit, 0);
+
+  if (rs6000_arch_flags)
+    rs6000_print_isa_options (stderr, 0, "rs6000_arch_flags", 0,
+			      rs6000_arch_flags);
 
-  rs6000_print_isa_options (stderr, 0, "TARGET_DEFAULT", TARGET_DEFAULT);
+  rs6000_print_isa_options (stderr, 0, "TARGET_DEFAULT", TARGET_DEFAULT, 0);
 
   fprintf (stderr, DEBUG_FMT_S, "--with-cpu default",
 	   OPTION_TARGET_CPU_DEFAULT ? OPTION_TARGET_CPU_DEFAULT : "<none>");
@@ -3625,7 +3707,7 @@  rs6000_option_override_internal (bool global_init_p)
 
   /* Print defaults.  */
   if ((TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) && global_init_p)
-    rs6000_print_isa_options (stderr, 0, "TARGET_DEFAULT", TARGET_DEFAULT);
+    rs6000_print_isa_options (stderr, 0, "TARGET_DEFAULT", TARGET_DEFAULT, 0);
 
   /* Remember the explicit arguments.  */
   if (global_init_p)
@@ -3756,6 +3838,8 @@  rs6000_option_override_internal (bool global_init_p)
       rs6000_isa_flags |= (flags & ~rs6000_isa_flags_explicit);
     }
 
+  rs6000_arch_flags = get_arch_flags (cpu_index);
+
   /* Don't expect powerpc64 enabled on those OSes with OS_MISSING_POWERPC64,
      since they do not save and restore the high half of the GPRs correctly
      in all cases.  If the user explicitly specifies it, we won't interfere
@@ -3875,7 +3959,8 @@  rs6000_option_override_internal (bool global_init_p)
 		         & ~rs6000_isa_flags_explicit);
 
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
-    rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags);
+    rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags,
+			      rs6000_arch_flags);
 
 #ifdef XCOFF_DEBUGGING_INFO
   /* For AIX default to 64-bit DWARF.  */
@@ -4237,7 +4322,8 @@  rs6000_option_override_internal (bool global_init_p)
 
   /* Print the options after updating the defaults.  */
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
-    rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
+    rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags,
+			      rs6000_arch_flags);
 
   /* E500mc does "better" if we inline more aggressively.  Respect the
      user's opinion, though.  */
@@ -4344,7 +4430,8 @@  rs6000_option_override_internal (bool global_init_p)
     TARGET_NO_FP_IN_TOC = 1;
 
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
-    rs6000_print_isa_options (stderr, 0, "before subtarget", rs6000_isa_flags);
+    rs6000_print_isa_options (stderr, 0, "before subtarget", rs6000_isa_flags,
+			      rs6000_arch_flags);
 
 #ifdef SUBTARGET_OVERRIDE_OPTIONS
   SUBTARGET_OVERRIDE_OPTIONS;
@@ -4411,7 +4498,8 @@  rs6000_option_override_internal (bool global_init_p)
     rs6000_isa_flags &= ~OPTION_MASK_PCREL_OPT;
 
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
-    rs6000_print_isa_options (stderr, 0, "after subtarget", rs6000_isa_flags);
+    rs6000_print_isa_options (stderr, 0, "after subtarget", rs6000_isa_flags,
+			      rs6000_arch_flags);
 
   rs6000_always_hint = (rs6000_tune != PROCESSOR_POWER4
 			&& rs6000_tune != PROCESSOR_POWER5
@@ -5902,27 +5990,28 @@  rs6000_machine_from_flags (void)
     return "ppc64";
 #endif
 
+  HOST_WIDE_INT arch_flags = rs6000_arch_flags;
   HOST_WIDE_INT flags = rs6000_isa_flags;
 
   /* Disable the flags that should never influence the .machine selection.  */
   flags &= ~(OPTION_MASK_PPC_GFXOPT | OPTION_MASK_PPC_GPOPT | OPTION_MASK_ISEL
 	     | OPTION_MASK_ALTIVEC);
 
-  if ((flags & (POWER11_MASKS_SERVER & ~ISA_3_1_MASKS_SERVER)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER11) != 0)
     return "power11";
-  if ((flags & (ISA_3_1_MASKS_SERVER & ~ISA_3_0_MASKS_SERVER)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER10) != 0)
     return "power10";
-  if ((flags & (ISA_3_0_MASKS_SERVER & ~ISA_2_7_MASKS_SERVER)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER9) != 0)
     return "power9";
-  if ((flags & (ISA_2_7_MASKS_SERVER & ~ISA_2_6_MASKS_SERVER)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER8) != 0)
     return "power8";
-  if ((flags & (ISA_2_6_MASKS_SERVER & ~ISA_2_5_MASKS_SERVER)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER7) != 0)
     return "power7";
-  if ((flags & (ISA_2_5_MASKS_SERVER & ~ISA_2_4_MASKS)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER6) != 0)
     return "power6";
-  if ((flags & (ISA_2_4_MASKS & ~ISA_2_1_MASKS)) != 0)
+  if ((arch_flags & ARCH_MASK_POWER5) != 0)
     return "power5";
-  if ((flags & ISA_2_1_MASKS) != 0)
+  if ((arch_flags & ARCH_MASK_POWER4) != 0)
     return "power4";
   if ((flags & OPTION_MASK_POWERPC64) != 0)
     return "ppc64";
@@ -24552,6 +24641,23 @@  static struct rs6000_opt_mask const rs6000_opt_masks[] =
   { "string",			0,				false, false },
 };
 
+/* Similar structure for the arch bits that are set via -mcpu=<xxx> and not via
+   a separate -m<yyy> option.  */
+struct rs6000_arch_mask {
+  const char *name;			/* option name */
+  const HOST_WIDE_INT mask;		/* mask to set */
+};
+
+#undef  ARCH_EXPAND
+#define ARCH_EXPAND(PROC, NAME)	{ NAME, ARCH_MASK_ ## PROC },
+
+static struct rs6000_arch_mask const rs6000_arch_masks[] =
+{
+#include "rs6000-arch.def"
+};
+
+#undef ARCH_EXPAND
+
 /* Option variables that we want to support inside attribute((target)) and
    #pragma GCC target operations.  */
 
@@ -25090,6 +25196,7 @@  rs6000_function_specific_save (struct cl_target_option *ptr,
 {
   ptr->x_rs6000_isa_flags = opts->x_rs6000_isa_flags;
   ptr->x_rs6000_isa_flags_explicit = opts->x_rs6000_isa_flags_explicit;
+  ptr->x_rs6000_arch_flags = opts->x_rs6000_arch_flags;
 }
 
 /* Restore the current options */
@@ -25102,6 +25209,7 @@  rs6000_function_specific_restore (struct gcc_options *opts,
 {
   opts->x_rs6000_isa_flags = ptr->x_rs6000_isa_flags;
   opts->x_rs6000_isa_flags_explicit = ptr->x_rs6000_isa_flags_explicit;
+  opts->x_rs6000_arch_flags = ptr->x_rs6000_arch_flags;
   (void) rs6000_option_override_internal (false);
 }
 
@@ -25112,10 +25220,12 @@  rs6000_function_specific_print (FILE *file, int indent,
 				struct cl_target_option *ptr)
 {
   rs6000_print_isa_options (file, indent, "Isa options set",
-			    ptr->x_rs6000_isa_flags);
+			    ptr->x_rs6000_isa_flags,
+			    ptr->x_rs6000_arch_flags);
 
   rs6000_print_isa_options (file, indent, "Isa options explicit",
-			    ptr->x_rs6000_isa_flags_explicit);
+			    ptr->x_rs6000_isa_flags_explicit,
+			    ptr->x_rs6000_arch_flags);
 }
 
 /* Helper function to print the current isa or misc options on a line.  */
@@ -25127,13 +25237,18 @@  rs6000_print_options_internal (FILE *file,
 			       HOST_WIDE_INT flags,
 			       const char *prefix,
 			       const struct rs6000_opt_mask *opts,
-			       size_t num_elements)
+			       size_t num_elements,
+			       HOST_WIDE_INT arch_flags,
+			       const char *arch_prefix,
+			       const struct rs6000_arch_mask *arch_masks,
+			       size_t num_arch)
 {
   size_t i;
   size_t start_column = 0;
   size_t cur_column;
   size_t max_column = 120;
   size_t prefix_len = strlen (prefix);
+  size_t arch_prefix_len = strlen (arch_prefix);
   size_t comma_len = 0;
   const char *comma = "";
 
@@ -25193,6 +25308,29 @@  rs6000_print_options_internal (FILE *file,
       comma_len = strlen (", ");
     }
 
+  /* Put out the architecture flag bits that are set via -mcpu=<xxx> and that
+     don't have a -m option.  */
+  for (i = 0; i < num_arch; i++)
+    {
+      if ((arch_flags & arch_masks[i].mask) != 0)
+	{
+	  const char *name = arch_masks[i].name;
+	  size_t len = comma_len + arch_prefix_len + strlen (name);
+
+	  cur_column += len;
+	  if (cur_column > max_column)
+	    {
+	      fprintf (stderr, ", \\\n%*s", (int)start_column, "");
+	      cur_column = start_column + len;
+	      comma = "";
+	    }
+
+	  fprintf (file, "%s%s%s", comma, arch_prefix, name);
+	  comma = ", ";
+	  comma_len = strlen (", ");
+	}
+    }
+
   fputs ("\n", file);
 }
 
@@ -25200,11 +25338,13 @@  rs6000_print_options_internal (FILE *file,
 
 static void
 rs6000_print_isa_options (FILE *file, int indent, const char *string,
-			  HOST_WIDE_INT flags)
+			  HOST_WIDE_INT flags, HOST_WIDE_INT arch_flags)
 {
   rs6000_print_options_internal (file, indent, string, flags, "-m",
 				 &rs6000_opt_masks[0],
-				 ARRAY_SIZE (rs6000_opt_masks));
+				 ARRAY_SIZE (rs6000_opt_masks),
+				 arch_flags, "arch=", &rs6000_arch_masks[0],
+				 ARRAY_SIZE (rs6000_arch_masks));
 }
 
 /* If the user used -mno-vsx, we need turn off all of the implicit ISA 2.06,
@@ -25294,7 +25434,7 @@  static int
 rs6000_clone_priority (tree fndecl)
 {
   tree fn_opts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
-  HOST_WIDE_INT isa_masks;
+  HOST_WIDE_INT arch_masks;
   int ret = CLONE_DEFAULT;
   tree attrs = lookup_attribute ("target", DECL_ATTRIBUTES (fndecl));
   const char *attrs_str = NULL;
@@ -25310,12 +25450,12 @@  rs6000_clone_priority (tree fndecl)
 	fn_opts = target_option_default_node;
 
       if (!fn_opts || !TREE_TARGET_OPTION (fn_opts))
-	isa_masks = rs6000_isa_flags;
+	arch_masks = rs6000_arch_flags;
       else
-	isa_masks = TREE_TARGET_OPTION (fn_opts)->x_rs6000_isa_flags;
+	arch_masks = TREE_TARGET_OPTION (fn_opts)->x_rs6000_arch_flags;
 
       for (ret = CLONE_MAX - 1; ret != 0; ret--)
-	if ((rs6000_clone_map[ret].isa_mask & isa_masks) != 0)
+	if ((rs6000_clone_map[ret].arch_mask & arch_masks) != 0)
 	  break;
     }
 
@@ -25795,6 +25935,8 @@  rs6000_can_inline_p (tree caller, tree callee)
   HOST_WIDE_INT callee_isa = callee_opts->x_rs6000_isa_flags;
   HOST_WIDE_INT caller_isa = caller_opts->x_rs6000_isa_flags;
   HOST_WIDE_INT explicit_isa = callee_opts->x_rs6000_isa_flags_explicit;
+  HOST_WIDE_INT callee_arch = callee_opts->x_rs6000_arch_flags;
+  HOST_WIDE_INT caller_arch = caller_opts->x_rs6000_arch_flags;
 
   cgraph_node *callee_node = cgraph_node::get (callee);
   if (ipa_fn_summaries && ipa_fn_summaries->get (callee_node) != NULL)
@@ -25818,7 +25960,8 @@  rs6000_can_inline_p (tree caller, tree callee)
      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))
+      && (caller_isa & explicit_isa) == (callee_isa & explicit_isa)
+      && (caller_arch & callee_arch) == callee_arch)
     ret = true;
 
   if (TARGET_DEBUG_TARGET)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 703be908d94..f0ffc72ae88 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2481,3 +2481,27 @@  while (0)
    issues have been resolved.  */
 #define RS6000_DISABLE_SCALAR_MODULO 1
 
+
+
+/* Create the architecture flags.  */
+/* Define an enumeration to number the architecture masks.  */
+#ifdef GCC_HWINT_H
+#undef  ARCH_EXPAND
+#define ARCH_EXPAND(PROC, NAME)	ARCH_ENUM_ ## PROC,
+
+enum {
+#include "rs6000-arch.def"
+  ARCH_ENUM_LAST
+};
+
+/* Create an architecture mask for the newer architectures (power6 and
+   up)..  */
+#undef  ARCH_EXPAND
+#define ARCH_EXPAND(PROC, NAME)						\
+  static const HOST_WIDE_INT ARCH_MASK_ ## PROC				\
+    = HOST_WIDE_INT_1 << ARCH_ENUM_ ## PROC;
+
+#include "rs6000-arch.def"
+
+#undef ARCH_EXPAND
+#endif	/* GCC_HWINT_H.  */
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 94323bd1db2..73dfb63a81c 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -36,6 +36,14 @@  HOST_WIDE_INT rs6000_isa_flags_explicit
 TargetSave
 HOST_WIDE_INT x_rs6000_isa_flags_explicit
 
+;; Arch bits that are set via -mcpu=<xxx> but don't have a user -m<processor>
+;; option
+Variable
+HOST_WIDE_INT rs6000_arch_flags = 0
+
+TargetSave
+HOST_WIDE_INT x_rs6000_arch_flags
+
 ;; Current processor
 TargetVariable
 enum processor_type rs6000_cpu = PROCESSOR_PPC603