Hi Kishan,
On 23/09/26 11:54 am, Kishan Parmar wrote:
> Hi All,
>
> Below patch is bootstrapped and regtested on power64le-linux.
>
> Thank you,
> Kishan
>
> The rs6000 built-in infrastructure previously supported only a single
> gating predicate per built-in stanza. This caused problems when a
> built-in required multiple conditions simultaneously. For example,
> __builtin_vsx_xvtlsbb_all_ones requires both Power10 ISA support
> (-mcpu=power10) and VSX support (-mvsx), but was gated only on
> [power10], causing compiler crashes when compiled with -mcpu=power10
> -mno-vsx.
>
> This patch extends the built-in infrastructure to support up to four
> comma-separated gating predicates in stanza headers, e.g.:
>
> [power10, vsx]
>
> All predicates are combined with AND logic all must be satisfied for
> the built-in to be enabled. existing single-predicate stanzas are parsed
> as before.
>
> The stanza keywords that hard-coded multi-predicate combinations
> (power6-64, power7-64, power8-vector, power9-64, power9-vector,
> power10-64, future-altivec, future-vsx) are removed and replaced by
> explicit comma-separated forms (e.g. [power9, vsx] instead of
> [power9-vector]).
>
> The two new static helpers get_enable_string() and check_single_enable()
> consolidate all predicate-to-string and predicate-to-target-flag mapping
> that was previously duplicated across the two functions.
>
> Note: only __builtin_vsx_xvtlsbb_all_ones and
> __builtin_vsx_xvtlsbb_all_zeros are moved to an explicit [power10, vsx]
> stanza in this patch. Full rework of rs6000-builtins.def to use
> multi-predicate stanzas throughout is left for a follow-on patch.
>
> This also fixes diagnostics for built-ins whose availability depends on
> both an ISA level and an additional feature. For example,
> __builtin_dmsetdmrz previously reported only "-mdense-math":
>
> error: '__builtin_dmsetdmrz' requires the '-mdense-math' option
>
> It now correctly reports both required predicates:
>
> error: '__builtin_dmsetdmrz' requires the '-mcpu=future' and
> '-mdense-math' options
>
> Similarly, MMA built-ins that require both Power10 ISA support and MMA
> support now report both missing requirements. For example,
> __builtin_mma_xxsetaccz previously reported only "-mmma", while it now
> reports:
>
> error: '__builtin_mma_xxsetaccz' requires the '-mcpu=power10' and
> '-mmma' options
>
> This ensures diagnostics accurately reflect all gating predicates required
> by a built-in.
>
> gcc/ChangeLog:
> PR target/125389
> * config/rs6000/rs6000-builtin.cc (get_enable_string): New static
> helper. map a single bif_enable to its option-string representation.
> (check_single_enable): New static helper. return true when a single
> bif_enable predicate is satisfied by the current target.
> (rs6000_invalid_builtin): Rewrite. Loop over enables[]. track
> ENB_M64 and ENB_IEEE128_HW separately for special diagnostic wording.
> emit a single error naming every predicate the built-in requires.
> (rs6000_builtin_is_supported): Rewrite. Loop over enables[] calling
> check_single_enable. return false on the first unsatisfied predicate.
> * config/rs6000/rs6000-builtins.def: Update file-header comment to
> document multi-predicate syntax. Replace composite stanza keywords
> with explicit comma-separated forms: [power6-64] -> [power6, m64],
> [power7-64] -> [power7, m64], [power8-vector] -> [power8, vsx],
> [power9-vector] -> [power9, vsx], [power9-64] -> [power9, m64],
> [power10-64] -> [power10, m64], [future-altivec] -> [future, altivec],
> [future-vsx] -> [future, vsx]. Move __builtin_vsx_xvtlsbb_all_ones
> and __builtin_vsx_xvtlsbb_all_zeros from the [power10] stanza to a
> new [power10, vsx] stanza.
> * config/rs6000/rs6000-gen-builtins.cc: Update file-header comment
> to document multi-predicate stanza syntax.
> (enum bif_stanza): Remove stanzas BSTZ_P6_64, BSTZ_P7_64, BSTZ_P8V,
> BSTZ_P9_64, BSTZ_P9V, BSTZ_P10_64, BSTZ_FUTURE_ALTIVEC,
> BSTZ_FUTURE_VSX. Add BSTZ_M64.
> (MAXBIFPREDICATES): New macro. maximum predicates per stanza.
> (curr_bif_num_predicates): New file-scope variable.
> (curr_bif_predicates): New file-scope array.
> (stanza_map): Remove composite entries. add "m64" -> BSTZ_M64.
> (enable_string): Remove composite ENB_* entries. add ENB_M64.
> (struct bifdata): Add fields num_predicates and predicates[].
> (parse_bif_stanza_predicates): New function. parse comma-separated
> predicates from a stanza header string.
> (parse_bif_entry): Store num_predicates and predicates[] into bifdata.
> (parse_bif_stanza): Call parse_bif_stanza_predicates instead of
> stanza_name_to_stanza directly.
> (write_decls): Emit ENB_M64. remove composite ENB_* values. emit
> PPC_MAXBIFPREDICATES macro. change bifdata::enable field to
> num_enables and enables[PPC_MAXBIFPREDICATES].
> (write_bif_static_init): Emit num_enables and enables[] initializer
> instead of single enable value.
>
> gcc/testsuite/ChangeLog:
> PR target/125389
> * gcc.target/powerpc/pr96125.c: Update expected error messages to
> include the '-mcpu=power10' requirement for MMA built-ins.
> ---
> gcc/config/rs6000/rs6000-builtin.cc | 209 ++++++++++++---------
> gcc/config/rs6000/rs6000-builtins.def | 48 +++--
> gcc/config/rs6000/rs6000-gen-builtins.cc | 143 ++++++++++----
> gcc/testsuite/gcc.target/powerpc/pr96125.c | 4 +-
> 4 files changed, 250 insertions(+), 154 deletions(-)
>
> diff --git a/gcc/config/rs6000/rs6000-builtin.cc
> b/gcc/config/rs6000/rs6000-builtin.cc
> index ad6f1fc09f4..9af2edca38c 100644
> --- a/gcc/config/rs6000/rs6000-builtin.cc
> +++ b/gcc/config/rs6000/rs6000-builtin.cc
> @@ -62,136 +62,75 @@ tree altivec_builtin_mask_for_load;
>
> /* **** General support functions **** */
>
> -/* Raise an error message for a builtin function that is called without the
> - appropriate target options being set. */
> +/* Helper function to get the option string for a single enable predicate.
> */
>
> -void
> -rs6000_invalid_builtin (enum rs6000_gen_builtins fncode)
> +static const char *
> +get_enable_string (bif_enable enable)
> {
> - size_t j = (size_t) fncode;
> - const char *name = rs6000_builtin_info[j].bifname;
> -
> - switch (rs6000_builtin_info[j].enable)
> + switch (enable)
> {
> case ENB_P5:
> - error ("%qs requires the %qs option", name, "-mcpu=power5");
> - break;
> + return "-mcpu=power5";
> case ENB_P6:
> - error ("%qs requires the %qs option", name, "-mcpu=power6");
> - break;
> - case ENB_P6_64:
> - error ("%qs requires the %qs option and either the %qs or %qs option",
> - name, "-mcpu=power6", "-m64", "-mpowerpc64");
> - break;
> + return "-mcpu=power6";
> case ENB_ALTIVEC:
> - error ("%qs requires the %qs option", name, "-maltivec");
> - break;
> + return "-maltivec";
> case ENB_CELL:
> - error ("%qs requires the %qs option", name, "-mcpu=cell");
> - break;
> + return "-mcpu=cell";
> case ENB_VSX:
> - error ("%qs requires the %qs option", name, "-mvsx");
> - break;
> + return "-mvsx";
> case ENB_P7:
> - error ("%qs requires the %qs option", name, "-mcpu=power7");
> - break;
> - case ENB_P7_64:
> - error ("%qs requires the %qs option and either the %qs or %qs option",
> - name, "-mcpu=power7", "-m64", "-mpowerpc64");
> - break;
> + return "-mcpu=power7";
> case ENB_P8:
> - error ("%qs requires the %qs option", name, "-mcpu=power8");
> - break;
> - case ENB_P8V:
> - error ("%qs requires the %qs and %qs options", name, "-mcpu=power8",
> - "-mvsx");
> - break;
> + return "-mcpu=power8";
> case ENB_P9:
> - error ("%qs requires the %qs option", name, "-mcpu=power9");
> - break;
> - case ENB_P9_64:
> - error ("%qs requires the %qs option and either the %qs or %qs option",
> - name, "-mcpu=power9", "-m64", "-mpowerpc64");
> - break;
> - case ENB_P9V:
> - error ("%qs requires the %qs and %qs options", name, "-mcpu=power9",
> - "-mvsx");
> - break;
> - case ENB_IEEE128_HW:
> - error ("%qs requires quad-precision floating-point arithmetic", name);
> - break;
> + return "-mcpu=power9";
> case ENB_DFP:
> - error ("%qs requires the %qs option", name, "-mhard-dfp");
> - break;
> + return "-mhard-dfp";
> case ENB_CRYPTO:
> - error ("%qs requires the %qs option", name, "-mcrypto");
> - break;
> + return "-mcrypto";
> case ENB_HTM:
> - error ("%qs requires the %qs option", name, "-mhtm");
> - break;
> + return "-mhtm";
> case ENB_P10:
> - error ("%qs requires the %qs option", name, "-mcpu=power10");
> - break;
> - case ENB_P10_64:
> - error ("%qs requires the %qs option and either the %qs or %qs option",
> - name, "-mcpu=power10", "-m64", "-mpowerpc64");
> - break;
> + return "-mcpu=power10";
> case ENB_MMA:
> - error ("%qs requires the %qs option", name, "-mmma");
> - break;
> + return "-mmma";
> case ENB_FUTURE:
> - error ("%qs requires the %qs option", name, "-mcpu=future");
> - break;
> - case ENB_FUTURE_ALTIVEC:
> - error ("%qs requires the %qs and %qs options", name, "-mcpu=future",
> - "-maltivec");
> - break;
> - case ENB_FUTURE_VSX:
> - error ("%qs requires the %qs and %qs options", name, "-mcpu=future",
> - "-mvsx");
> - break;
> + return "-mcpu=future";
> case ENB_DM:
> - error ("%qs requires the %qs option", name, "-mdense-math");
> - break;
> + return "-mdense-math";
> default:
> case ENB_ALWAYS:
> + case ENB_M64:
> + case ENB_IEEE128_HW:
> gcc_unreachable ();
> }
> + gcc_unreachable ();
> }
>
> -/* Check whether a builtin function is supported in this target
> - configuration. */
> -bool
> -rs6000_builtin_is_supported (enum rs6000_gen_builtins fncode)
> +/* Helper function to check if a single enable predicate is satisfied. */
> +
> +static bool
> +check_single_enable (bif_enable enable)
> {
> - switch (rs6000_builtin_info[(size_t) fncode].enable)
> + switch (enable)
> {
> case ENB_ALWAYS:
> return true;
> + case ENB_M64:
> + return TARGET_POWERPC64;
> case ENB_P5:
> return TARGET_POPCNTB;
> case ENB_P6:
> return TARGET_CMPB;
> - case ENB_P6_64:
> - return TARGET_CMPB && TARGET_POWERPC64;
> case ENB_P7:
> return TARGET_POPCNTD;
> - case ENB_P7_64:
> - return TARGET_POPCNTD && TARGET_POWERPC64;
> case ENB_P8:
> return TARGET_POWER8;
> - case ENB_P8V:
> - return TARGET_P8_VECTOR;
> case ENB_P9:
> return TARGET_MODULO;
> - case ENB_P9_64:
> - return TARGET_MODULO && TARGET_POWERPC64;
> - case ENB_P9V:
> - return TARGET_P9_VECTOR;
> case ENB_P10:
> return TARGET_POWER10;
> - case ENB_P10_64:
> - return TARGET_POWER10 && TARGET_POWERPC64;
> case ENB_ALTIVEC:
> return TARGET_ALTIVEC;
> case ENB_VSX:
> @@ -210,10 +149,6 @@ rs6000_builtin_is_supported (enum rs6000_gen_builtins
> fncode)
> return TARGET_MMA;
> case ENB_FUTURE:
> return TARGET_FUTURE;
> - case ENB_FUTURE_ALTIVEC:
> - return TARGET_FUTURE && TARGET_ALTIVEC;
> - case ENB_FUTURE_VSX:
> - return TARGET_FUTURE && TARGET_VSX;
> case ENB_DM:
> return TARGET_DMF;
> default:
> @@ -222,6 +157,92 @@ rs6000_builtin_is_supported (enum rs6000_gen_builtins
> fncode)
> gcc_unreachable ();
> }
>
> +/* Raise an error message for a builtin function that is called without the
> + appropriate target options being set. All predicates the builtin requires
> + are reported so the user can see the full set at once. */
Currently, rs6000_invalid_builtin() checks all required features without
checking whether they are already enabled by the user.
As a result, the error message may list options that the user has already
specified.
For example:
1. -mcpu=power10 -mno-vsx
Test case:
#include <altivec.h>
extern vector signed char abc;
int main()
{
return __builtin_vsx_xvtlsbb_all_ones (abc);
}
The diagnostic reports both -mcpu=power10 and -mvsx, even though -mcpu=power10
is already specified.
2. -m64 -mcpu=power5
Test case:
unsigned long long test (unsigned long long a, unsigned long long b)
{
return __builtin_cmpb (a, b);
}
The diagnostic reports -mcpu=power6 and either -m64 or -mpowerpc64, even though
-m64 is already specified.
> +
> +void
> +rs6000_invalid_builtin (enum rs6000_gen_builtins fncode)
> +{
> + size_t j = (size_t) fncode;
> + const char *name = rs6000_builtin_info[j].bifname;
> + int num_enables = rs6000_builtin_info[j].num_enables;
> +
> + if (num_enables == 1
> + && rs6000_builtin_info[j].enables[0] == ENB_IEEE128_HW)
> + {
> + error ("%qs requires quad-precision floating-point arithmetic", name);
> + return;
> + }
> +
> + /* Collect all predicates the builtin requires. */
> + const char *req[PPC_MAXBIFPREDICATES];
> + int num_req = 0;
> + bool has_m64 = false;
> +
> + for (int i = 0; i < num_enables; i++)
> + {
> + bif_enable enb = rs6000_builtin_info[j].enables[i];
> + if (enb == ENB_M64)
> + has_m64 = true;
> + else
> + req[num_req++] = get_enable_string (enb);
> + }
> +
> + /* ENB_M64 has two equivalent spellings; append its wording last so
> + that all plain option names come first in the message. */
> + if (has_m64)
> + {
> + if (num_req == 0)
> + error ("%qs requires either the %qs or %qs option",
> + name, "-m64", "-mpowerpc64");
> + else if (num_req == 1)
> + error ("%qs requires the %qs option and either the %qs or %qs option",
> + name, req[0], "-m64", "-mpowerpc64");
> + else if (num_req == 2)
> + error ("%qs requires the %qs and %qs options"
> + " and either the %qs or %qs option",
> + name, req[0], req[1], "-m64", "-mpowerpc64");
> + else if (num_req == 3)
> + error ("%qs requires the %qs, %qs, and %qs options"
> + " and either the %qs or %qs option",
> + name, req[0], req[1], req[2], "-m64", "-mpowerpc64");
> + return;
> + }
> +
> + /* Report all required options. */
> + if (num_req == 1)
> + error ("%qs requires the %qs option", name, req[0]);
> + else if (num_req == 2)
> + error ("%qs requires the %qs and %qs options",
> + name, req[0], req[1]);
> + else if (num_req == 3)
> + error ("%qs requires the %qs, %qs, and %qs options",
> + name, req[0], req[1], req[2]);
> + else if (num_req == 4)
> + error ("%qs requires the %qs, %qs, %qs, and %qs options",
> + name, req[0], req[1], req[2], req[3]);
> +}
Can we add an 'else gcc_unreachable ();' here to catch unexpected 'num_req'
values?
> +
> +/* Check whether a builtin function is supported in this target
> + configuration. For functions with multiple gating predicates,
> + ALL predicates must be satisfied (AND logic). */
> +
> +bool
> +rs6000_builtin_is_supported (enum rs6000_gen_builtins fncode)
> +{
> + size_t j = (size_t) fncode;
> + int num_enables = rs6000_builtin_info[j].num_enables;
> +
> + for (int i = 0; i < num_enables; i++)
> + {
> + if (!check_single_enable (rs6000_builtin_info[j].enables[i]))
> + return false;
> + }
> +
> + return true;
> +}
> +
> /* Target hook for early folding of built-ins, shamelessly stolen
> from ia64.cc. */
>
> diff --git a/gcc/config/rs6000/rs6000-builtins.def
> b/gcc/config/rs6000/rs6000-builtins.def
> index 4b7d21cdb81..bbd8a2d4b79 100644
> --- a/gcc/config/rs6000/rs6000-builtins.def
> +++ b/gcc/config/rs6000/rs6000-builtins.def
> @@ -31,7 +31,15 @@
> ;
> ; [power9]
> ;
> -; The bracketed gating predicate is the only information allowed on
> +; Multiple gating predicates can be specified using comma-separated values.
> +; When multiple predicates are specified, ALL predicates must be satisfied
> +; (AND logic) for the built-in to be enabled. For example:
> +;
> +; [power10,vsx]
> +;
> +; This means the built-in requires both -mcpu=power10 AND -mvsx options.
> +;
> +; The bracketed gating predicate(s) are the only information allowed on
> ; the stanza header line, other than whitespace.
> ;
> ; Following the stanza header are two lines for each function: the
> @@ -286,7 +294,7 @@
>
>
> ; Power6 builtins requiring 64-bit GPRs (even with 32-bit addressing).
> -[power6-64]
> +[power6, m64]
> const signed long __builtin_p6_cmpb (signed long, signed long);
> CMPB cmpbdi3 {no32bit}
>
> @@ -1861,7 +1869,7 @@
>
>
> ; Power7 builtins requiring 64-bit GPRs (even with 32-bit addressing).
> -[power7-64]
> +[power7, m64]
> const signed long long __builtin_divde (signed long long, signed long
> long);
> DIVDE dive_di {}
>
> @@ -1871,7 +1879,7 @@
>
>
> ; Power8 vector built-ins.
> -[power8-vector]
> +[power8, vsx]
> const vsll __builtin_altivec_abs_v2di (vsll);
> ABS_V2DI absv2di2 {}
>
> @@ -2312,7 +2320,7 @@
>
>
> ; Power9 vector builtins.
> -[power9-vector]
> +[power9, vsx]
> const vss __builtin_altivec_convert_4f32_8f16 (vf, vf);
> CONVERT_4F32_8F16 convert_4f32_8f16 {}
>
> @@ -2659,7 +2667,7 @@
> const signed int __builtin_vsx_scalar_extract_exp (double);
> VSEEDP xsxexpdp_si {}
>
> -[power9-64]
> +[power9, m64]
> void __builtin_altivec_xst_len_r (vsc, void *, long);
> XST_LEN_R xst_len_r {}
>
> @@ -3335,12 +3343,6 @@
> const vuq __builtin_vsx_vmsumcud (vull, vull, vuq);
> VMSUMCUD vmsumcud {}
>
> - const signed int __builtin_vsx_xvtlsbb_all_ones (vsc);
> - XVTLSBB_ONES xvtlsbbo {}
> -
> - const signed int __builtin_vsx_xvtlsbb_all_zeros (vsc);
> - XVTLSBB_ZEROS xvtlsbbz {}
> -
> const vf __builtin_vsx_vxxsplti32dx_v4sf (vf, const int<1>, float);
> VXXSPLTI32DX_V4SF xxsplti32dx_v4sf {}
>
> @@ -3442,7 +3444,16 @@
> ZE_LXVRDX vsx_lxvrdx {lxvrze}
>
>
> -[power10-64]
> +; Power10 builtins that requires -mvsx.
Typo: change requires to require.
> +[power10, vsx]
> + const signed int __builtin_vsx_xvtlsbb_all_ones (vsc);
> + XVTLSBB_ONES xvtlsbbo {}
> +
> + const signed int __builtin_vsx_xvtlsbb_all_zeros (vsc);
> + XVTLSBB_ZEROS xvtlsbbz {}
> +
> +
> +[power10, m64]
> const unsigned long long __builtin_cfuged (unsigned long long, \
> unsigned long long);
> CFUGED cfuged {}
> @@ -3463,8 +3474,8 @@
> unsigned long long);
> PEXTD pextd {}
>
> -
> -[mma]
> +; Power10 built-ins that requires -mmma
Typo: change requires to require.
> +[power10, mma]
> void __builtin_mma_assemble_acc (v512 *, vuc, vuc, vuc, vuc);
> ASSEMBLE_ACC nothing {mma,mmaint}
>
> @@ -3942,7 +3953,7 @@
> void __builtin_vsx_stxvp (v256, unsigned long, const v256 *);
> STXVP nothing {mma,pair}
>
> -[future-vsx]
> +[future, vsx]
> const vus __builtin_vsx_xvmulhuh (vus, vus);
> XVMULHUH umulv8hi3_highpart {}
>
> @@ -4071,7 +4082,7 @@
> const vuc __builtin_galois_field_mult_xts (vuc, vuc);
> XXGFMUL128XTS xxgfmul128xts {}
>
> -[future-altivec]
> +[future, altivec]
> const vus __builtin_altivec_uncompresshn (vuc, vui);
> VUCMPRHN altivec_vucmprhn {}
>
> @@ -4096,7 +4107,8 @@
> const vf __builtin_altivec_unpack_int8_to_fp32 (vui, const int<2>);
> VUPKINT8TOFP32 altivec_vupkint8tofp32 {}
>
> -[dm]
> +; future built-ins that requires -mdense-math
Typo: change requires to require.
Thanks,
Jeevitha.
> +[future, dm]
> void __builtin_dmsetdmrz (dmr1024 *);
> DMSETDMRZ nothing {dm,dmint}
>
> diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc
> b/gcc/config/rs6000/rs6000-gen-builtins.cc
> index 08068ba78fd..c97c246df32 100644
> --- a/gcc/config/rs6000/rs6000-gen-builtins.cc
> +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc
> @@ -39,7 +39,15 @@ along with GCC; see the file COPYING3. If not see
>
> [power9]
>
> - The bracketed gating predicate is the only information allowed on
> + Multiple gating predicates can be specified using comma-separated
> + values. When multiple predicates are specified, ALL predicates must
> + be satisfied (AND logic) for the built-in to be enabled. For example:
> +
> + [power10,vsx]
> +
> + This means the built-in requires both -mcpu=power10 AND -mvsx options.
> +
> + The bracketed gating predicate(s) are the only information allowed on
> the stanza header line, other than whitespace.
>
> Following the stanza header are two lines for each function: the
> @@ -215,34 +223,33 @@ enum void_status
> enum bif_stanza
> {
> BSTZ_ALWAYS,
> + BSTZ_M64,
> BSTZ_P5,
> BSTZ_P6,
> - BSTZ_P6_64,
> BSTZ_ALTIVEC,
> BSTZ_CELL,
> BSTZ_VSX,
> BSTZ_P7,
> - BSTZ_P7_64,
> BSTZ_P8,
> - BSTZ_P8V,
> BSTZ_P9,
> - BSTZ_P9_64,
> - BSTZ_P9V,
> BSTZ_IEEE128_HW,
> BSTZ_DFP,
> BSTZ_CRYPTO,
> BSTZ_HTM,
> BSTZ_P10,
> - BSTZ_P10_64,
> BSTZ_MMA,
> BSTZ_FUTURE,
> - BSTZ_FUTURE_ALTIVEC,
> - BSTZ_FUTURE_VSX,
> BSTZ_DM,
> NUMBIFSTANZAS
> };
>
> +/* Maximum number of predicates that can be specified for a single
> + stanza. */
> +#define MAXBIFPREDICATES 4
> +
> static bif_stanza curr_bif_stanza;
> +static int curr_bif_num_predicates = 0;
> +static bif_stanza curr_bif_predicates[MAXBIFPREDICATES];
>
> struct stanza_entry
> {
> @@ -253,58 +260,44 @@ struct stanza_entry
> static stanza_entry stanza_map[NUMBIFSTANZAS] =
> {
> { "always", BSTZ_ALWAYS },
> + { "m64", BSTZ_M64 },
> { "power5", BSTZ_P5 },
> { "power6", BSTZ_P6 },
> - { "power6-64", BSTZ_P6_64 },
> { "altivec", BSTZ_ALTIVEC },
> { "cell", BSTZ_CELL },
> { "vsx", BSTZ_VSX },
> { "power7", BSTZ_P7 },
> - { "power7-64", BSTZ_P7_64 },
> { "power8", BSTZ_P8 },
> - { "power8-vector", BSTZ_P8V },
> { "power9", BSTZ_P9 },
> - { "power9-64", BSTZ_P9_64 },
> - { "power9-vector", BSTZ_P9V },
> { "ieee128-hw", BSTZ_IEEE128_HW },
> { "dfp", BSTZ_DFP },
> { "crypto", BSTZ_CRYPTO },
> { "htm", BSTZ_HTM },
> { "power10", BSTZ_P10 },
> - { "power10-64", BSTZ_P10_64 },
> { "mma", BSTZ_MMA },
> { "future", BSTZ_FUTURE },
> - { "future-altivec", BSTZ_FUTURE_ALTIVEC },
> - { "future-vsx", BSTZ_FUTURE_VSX },
> { "dm", BSTZ_DM }
> };
>
> static const char *enable_string[NUMBIFSTANZAS] =
> {
> "ENB_ALWAYS",
> + "ENB_M64",
> "ENB_P5",
> "ENB_P6",
> - "ENB_P6_64",
> "ENB_ALTIVEC",
> "ENB_CELL",
> "ENB_VSX",
> "ENB_P7",
> - "ENB_P7_64",
> "ENB_P8",
> - "ENB_P8V",
> "ENB_P9",
> - "ENB_P9_64",
> - "ENB_P9V",
> "ENB_IEEE128_HW",
> "ENB_DFP",
> "ENB_CRYPTO",
> "ENB_HTM",
> "ENB_P10",
> - "ENB_P10_64",
> "ENB_MMA",
> "ENB_FUTURE",
> - "ENB_FUTURE_ALTIVEC",
> - "ENB_FUTURE_VSX",
> "ENB_DM"
> };
>
> @@ -432,6 +425,8 @@ struct prototype
> struct bifdata
> {
> int stanza;
> + int num_predicates;
> + int predicates[MAXBIFPREDICATES];
> fnkinds kind;
> prototype proto;
> char *idname;
> @@ -837,6 +832,56 @@ stanza_name_to_stanza (const char *stanza_name)
> return BSTZ_ALWAYS;
> }
>
> +/* Parse comma-separated gating predicates from a stanza header and populate
> + the predicates array. Each predicate is specified by a stanza name (e.g.,
> + "power10", "vsx") that represents a gating condition that must be
> satisfied
> + for the built-in to be enabled. Multiple predicates are combined with AND
> + logic. Returns the number of predicates parsed. */
> +
> +static int
> +parse_bif_stanza_predicates (char *predicates_str, bif_stanza *predicates)
> +{
> + int num_predicates = 0;
> + char *predicate_name = predicates_str;
> + char *comma_pos;
> +
> + while (predicate_name && num_predicates < MAXBIFPREDICATES)
> + {
> + /* Find the next comma or end of string. */
> + comma_pos = strchr (predicate_name, ',');
> + if (comma_pos)
> + *comma_pos = '\0';
> +
> + /* Trim leading and trailing whitespace from predicate name. */
> + while (*predicate_name == ' ' || *predicate_name == '\t')
> + predicate_name++;
> +
> + char *end = predicate_name + strlen (predicate_name) - 1;
> + while (end > predicate_name && (*end == ' ' || *end == '\t'))
> + {
> + *end = '\0';
> + end--;
> + }
> +
> + if (*predicate_name != '\0')
> + {
> + /* Convert predicate name (stanza name) to stanza enum. */
> + predicates[num_predicates] = stanza_name_to_stanza (predicate_name);
> + num_predicates++;
> + }
> +
> + if (comma_pos)
> + predicate_name = comma_pos + 1;
> + else
> + break;
> + }
> +
> + if (num_predicates >= MAXBIFPREDICATES && strchr (predicate_name, ','))
> + fatal ("Too many predicates in stanza header.\n");
> +
> + return num_predicates;
> +}
> +
> /* Match one of the allowable base types. Consumes one token unless the
> token is "long", which must be paired with a second "long". Optionally
> consumes a following '*' token for pointers. Return 1 for success,
> @@ -1831,6 +1876,9 @@ parse_bif_entry (void)
>
> curr_bif = num_bifs++;
> bifs[curr_bif].stanza = curr_bif_stanza;
> + bifs[curr_bif].num_predicates = curr_bif_num_predicates;
> + for (int i = 0; i < curr_bif_num_predicates; i++)
> + bifs[curr_bif].predicates[i] = curr_bif_predicates[i];
>
> /* Read the first token and see if it is a function modifier. */
> consume_whitespace ();
> @@ -1936,14 +1984,25 @@ parse_bif_stanza (void)
> }
> safe_inc_pos ();
>
> - const char *stanza_name = match_to_right_bracket ();
> - if (!stanza_name)
> + const char *stanza_name_const = match_to_right_bracket ();
> + if (!stanza_name_const)
> {
> diag (pos, "no expression found in stanza header.\n");
> return PC_PARSEFAIL;
> }
>
> - curr_bif_stanza = stanza_name_to_stanza (stanza_name);
> + /* Make a mutable copy since parse_bif_stanza_predicates modifies the
> + string. */
> + char *stanza_name = strdup (stanza_name_const);
> +
> + curr_bif_num_predicates = parse_bif_stanza_predicates (stanza_name,
> + curr_bif_predicates);
> +
> + free (stanza_name);
> +
> + /* Store the primary (first) stanza in curr_bif_stanza for
> + backward compatibility. */
> + curr_bif_stanza = curr_bif_predicates[0];
>
> if (linebuf[pos] != ']')
> {
> @@ -2270,37 +2329,32 @@ write_decls (void)
>
> fprintf (header_file, "enum bif_enable {\n");
> fprintf (header_file, " ENB_ALWAYS,\n");
> + fprintf (header_file, " ENB_M64,\n");
> fprintf (header_file, " ENB_P5,\n");
> fprintf (header_file, " ENB_P6,\n");
> - fprintf (header_file, " ENB_P6_64,\n");
> fprintf (header_file, " ENB_ALTIVEC,\n");
> fprintf (header_file, " ENB_CELL,\n");
> fprintf (header_file, " ENB_VSX,\n");
> fprintf (header_file, " ENB_P7,\n");
> - fprintf (header_file, " ENB_P7_64,\n");
> fprintf (header_file, " ENB_P8,\n");
> - fprintf (header_file, " ENB_P8V,\n");
> fprintf (header_file, " ENB_P9,\n");
> - fprintf (header_file, " ENB_P9_64,\n");
> - fprintf (header_file, " ENB_P9V,\n");
> fprintf (header_file, " ENB_IEEE128_HW,\n");
> fprintf (header_file, " ENB_DFP,\n");
> fprintf (header_file, " ENB_CRYPTO,\n");
> fprintf (header_file, " ENB_HTM,\n");
> fprintf (header_file, " ENB_P10,\n");
> - fprintf (header_file, " ENB_P10_64,\n");
> fprintf (header_file, " ENB_MMA,\n");
> fprintf (header_file, " ENB_FUTURE,\n");
> - fprintf (header_file, " ENB_FUTURE_ALTIVEC,\n");
> - fprintf (header_file, " ENB_FUTURE_VSX,\n");
> fprintf (header_file, " ENB_DM\n");
> fprintf (header_file, "};\n\n");
>
> fprintf (header_file, "#define PPC_MAXRESTROPNDS 3\n");
> + fprintf (header_file, "#define PPC_MAXBIFPREDICATES 4\n");
> fprintf (header_file, "struct bifdata\n");
> fprintf (header_file, "{\n");
> fprintf (header_file, " const char *bifname;\n");
> - fprintf (header_file, " bif_enable enable;\n");
> + fprintf (header_file, " int num_enables;\n");
> + fprintf (header_file, " bif_enable enables[PPC_MAXBIFPREDICATES];\n");
> fprintf (header_file, " insn_code icode;\n");
> fprintf (header_file, " int nargs;\n");
> fprintf (header_file, " int bifattrs;\n");
> @@ -2527,7 +2581,7 @@ write_bif_static_init (void)
> fprintf (init_file, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n");
> fprintf (init_file, " {\n");
> fprintf (init_file, " { /* RS6000_BIF_NONE: */\n");
> - fprintf (init_file, " \"\", ENB_ALWAYS, CODE_FOR_nothing, 0,\n");
> + fprintf (init_file, " \"\", 0, {ENB_ALWAYS}, CODE_FOR_nothing, 0,\n");
> fprintf (init_file, " 0, {0, 0, 0}, {RES_NONE, RES_NONE,
> RES_NONE},\n");
> fprintf (init_file, " {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n");
> fprintf (init_file, " },\n");
> @@ -2537,8 +2591,17 @@ write_bif_static_init (void)
> fprintf (init_file, " { /* RS6000_BIF_%s: */\n", bifp->idname);
> fprintf (init_file, " /* bifname */\t\"%s\",\n",
> bifp->proto.bifname);
> - fprintf (init_file, " /* enable*/\t%s,\n",
> - enable_string[bifp->stanza]);
> + /* Output num_enables and enables array. */
> + fprintf (init_file, " /* num_enables */\t%d,\n",
> + bifp->num_predicates);
> + fprintf (init_file, " /* enables */\t{");
> + for (int j = 0; j < bifp->num_predicates; j++)
> + {
> + if (j > 0)
> + fprintf (init_file, ", ");
> + fprintf (init_file, "%s", enable_string[bifp->predicates[j]]);
> + }
> + fprintf (init_file, "},\n");
> fprintf (init_file, " /* icode */\tCODE_FOR_%s,\n",
> bifp->patname);
> fprintf (init_file, " /* nargs */\t%d,\n",
> diff --git a/gcc/testsuite/gcc.target/powerpc/pr96125.c
> b/gcc/testsuite/gcc.target/powerpc/pr96125.c
> index a4bb0d55786..29711cac796 100644
> --- a/gcc/testsuite/gcc.target/powerpc/pr96125.c
> +++ b/gcc/testsuite/gcc.target/powerpc/pr96125.c
> @@ -15,7 +15,7 @@ void
> test1 (__vector_quad *dst)
> {
> __vector_quad acc;
> - __builtin_mma_xxsetaccz (&acc); /* { dg-error "'__builtin_mma_xxsetaccz'
> requires the '-mmma' option" } */
> + __builtin_mma_xxsetaccz (&acc); /* { dg-error "'__builtin_mma_xxsetaccz'
> requires the '-mcpu=power10' and '-mmma' options" } */
> *dst = acc;
> }
>
> @@ -41,7 +41,7 @@ void
> test4 (__vector_quad *dst)
> {
> __vector_quad acc;
> - __builtin_mma_xxmfacc (&acc); /* { dg-error "'__builtin_mma_xxmfacc'
> requires the '-mmma' option" } */
> + __builtin_mma_xxmfacc (&acc); /* { dg-error "'__builtin_mma_xxmfacc'
> requires the '-mcpu=power10' and '-mmma' options" } */
> *dst = acc;
> }
>