new file mode 100644
@@ -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")
@@ -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)
@@ -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. */
@@ -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