This patch adds warning messages and test cases to an initial patch already submitted and committed to the trunk on October 26, 2016. The earlier patch disables initialization of built-in functions which depend on assembler capabilities that are not supported by the associated tool chain.
The original patch was submitted before the work was considered complete because it was desired to expedite a fix to allow builds on Power7. At the time the original patch was submitted for approval, the following additional tasks were planned. 1. Fail with an assertion error instead of an internal compiler error if built-in functions are ever defined for which the corresponding instruction pattern is not supported by the current compiler configuration. 2. Issue a warning message whenever a command-line -mcpu=XXX request seeks to configure support for a CPU version which is not supported by the accompanying assembler. Besides addressing the above tasks, this new patch also adds a number of tests to exercise different target configurations. The patch has been tested with three different tool chains supporting up to power7, power8, and power9 respectively. It has successfully bootstrapped and tested without regressions on powerpc64le-unknown-linux and powerpc-unknown-linux (big-endian, with both -m32 and -m64 target options) with no regressions. Is this patch ok for trunk? gcc/ChangeLog: 2016-12-08 Kelvin Nilsen <kel...@gcc.gnu.org> PR target/78056 * config/rs6000/rs6000.c: Provide default macro definitions for HAVE_AS_POPCNB, HAVE_AS_DFP, HAVE_AS_POPCNTD, HAVE_AS_POWER8, HAVE_AS_POWER9. (rs6000_option_override_internal): Add code to issue warning messages if a requested CPU configuration is not supported by the binary (assembler and loader) toolchain. (spe_init_builtins): Add two assertions to prevent ICE if attempt is made to define a built-in function that has been disabled. (paired_init_builtins): Add assertion to prevent ICE if attempt is made to define a built-in function that has been disabled. (altivec_init_builtins): Add comment explaining why definition of the DST built-in functions is not preceded by an assertion check. Add assertions to prevent ICE if attempts are made to define an altivec predicate or an abs* built-in function that has been disabled. (htm_init_builtins): Add comment explaining why definition of the htm built-in functions is not preceded by an assertion check. gcc/testsuite/ChangeLog: 2016-12-08 Kelvin Nilsen <kel...@gcc.gnu.org> PR target/78056 * gcc.target/powerpc/pr78056-1.c: New test. * gcc.target/powerpc/pr78056-2.c: New test. * gcc.target/powerpc/pr78056-3.c: New test. * gcc.target/powerpc/pr78056-4.c: New test. * gcc.target/powerpc/pr78056-5.c: New test. * gcc.target/powerpc/pr78056-6.c: New test. * gcc.target/powerpc/pr78056-7.c: New test. * gcc.target/powerpc/pr78056-8.c: New test. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 241606) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -84,6 +84,22 @@ #define min(A,B) ((A) < (B) ? (A) : (B)) #define max(A,B) ((A) > (B) ? (A) : (B)) +#ifndef HAVE_AS_POWER9 +#define HAVE_AS_POWER9 0 +#endif +#ifndef HAVE_AS_POWER8 +#define HAVE_AS_POWER8 0 +#endif +#ifndef HAVE_AS_POPCNTD +#define HAVE_AS_POPCNTD 0 +#endif +#ifndef HAVE_AS_DFP +#define HAVE_AS_DFP 0 +#endif +#ifndef HAVE_AS_POPCNTB +#define HAVE_AS_POPCNTB 0 +#endif + /* Structure used to define the rs6000 stack */ typedef struct rs6000_stack { int reload_completed; /* stack info won't change from here on */ @@ -3860,6 +3876,62 @@ rs6000_option_override_internal (bool global_init_ gcc_assert (cpu_index >= 0); + if (have_cpu) + { + if (!HAVE_AS_POWER9 + && (processor_target_table[rs6000_cpu_index].processor + == PROCESSOR_POWER9)) + { + have_cpu = false; + warning (0, "will not generate power9 instructions because " + "assembler lacks power9 support"); + } + if (!HAVE_AS_POWER8 + && (processor_target_table[rs6000_cpu_index].processor + == PROCESSOR_POWER8)) + { + have_cpu = false; + warning (0, "will not generate power8 instructions because " + "assembler lacks power8 support"); + } + if (!HAVE_AS_POPCNTD + && (processor_target_table[rs6000_cpu_index].processor + == PROCESSOR_POWER7)) + { + have_cpu = false; + warning (0, "will not generate power7 instructions because " + "assembler lacks power7 support"); + } + if (!HAVE_AS_DFP + && (processor_target_table[rs6000_cpu_index].processor + == PROCESSOR_POWER6)) + { + have_cpu = false; + warning (0, "will not generate power6 instructions because " + "assembler lacks power6 support"); + } + if (!HAVE_AS_POPCNTB + && (processor_target_table[rs6000_cpu_index].processor + == PROCESSOR_POWER5)) + { + have_cpu = false; + warning (0, "will not generate power5 instructions because " + "assembler lacks power5 support"); + } + + if (!have_cpu) + { + /* PowerPC 64-bit LE requires at least ISA 2.07. */ + const char *default_cpu = ((!TARGET_POWERPC64) + ? "powerpc" + : ((BYTES_BIG_ENDIAN) + ? "powerpc64" + : "powerpc64le")); + + rs6000_cpu_index = cpu_index = rs6000_cpu_name_lookup (default_cpu); + } + } + /* If we have a cpu, either through an explicit -mcpu=<xxx> or if the compiler was configured with --with-cpu=<xxx>, replace all of the ISA bits with those from the cpu, except for options that were explicitly set. If @@ -17074,6 +17146,8 @@ spe_init_builtins (void) continue; } + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode > 0); switch (insn_data[d->icode].operand[1].mode) { case V2SImode: @@ -17104,6 +17178,8 @@ spe_init_builtins (void) continue; } + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode > 0); switch (insn_data[d->icode].operand[1].mode) { case V2SImode: @@ -17171,6 +17247,9 @@ paired_init_builtins (void) continue; } + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode > 0); + if (TARGET_DEBUG_BUILTIN) fprintf (stderr, "paired pred #%d, insn = %s [%d], mode = %s\n", (int)i, get_insn_name (d->icode), (int)d->icode, @@ -17540,6 +17619,8 @@ altivec_init_builtins (void) { HOST_WIDE_INT mask = d->mask; + /* It is expected that these dst built-in functions have + d->icode equal to CODE_FOR_nothing. */ if ((mask & builtin_mask) != mask) { if (TARGET_DEBUG_BUILTIN) @@ -17569,7 +17650,11 @@ altivec_init_builtins (void) if (rs6000_overloaded_builtin_p (d->code)) mode1 = VOIDmode; else - mode1 = insn_data[d->icode].operand[1].mode; + { + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode > 0); + mode1 = insn_data[d->icode].operand[1].mode; + } switch (mode1) { @@ -17617,6 +17702,8 @@ altivec_init_builtins (void) continue; } + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode > 0); mode0 = insn_data[d->icode].operand[0].mode; switch (mode0) @@ -17804,6 +17891,9 @@ htm_init_builtins (void) tree rettype; tree argtype; + /* It is expected that these htm built-in functions have + d->icode equal to CODE_FOR_nothing. */ + if (TARGET_32BIT && TARGET_POWERPC64) gpr_type_node = long_long_unsigned_type_node; else Index: gcc/testsuite/gcc.target/powerpc/pr78056-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-1.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-1.c (revision 241861) @@ -0,0 +1,18 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power8" } */ + +/* This test should succeed on both 32- and 64-bit configurations. */ +#include <altivec.h> + +/* Though the command line specifies power8 target, this function is + to support power9. */ +__attribute__((target("cpu=power9"))) +int get_random () +{ + return __builtin_darn_32 (); +} + +/* { dg-final { scan-assembler "darn" } } */ Index: gcc/testsuite/gcc.target/powerpc/pr78056-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-2.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-2.c (revision 242019) @@ -0,0 +1,19 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-skip-if "" { powerpc_p9vector_ok } } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power8" } */ + +/* This test should succeed on both 32- and 64-bit configurations. */ +#include <altivec.h> + +/* Though the command line specifies power8 target, this function is + to support power9. Expect an error message here because this target + does not support power9. */ +__attribute__((target("cpu=power9"))) +int get_random () +{ /* { dg-warning "lacks power9 support" } */ + return __builtin_darn_32 (); /* { dg-warning "implicit declaration" } */ +} + Index: gcc/testsuite/gcc.target/powerpc/pr78056-3.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-3.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-3.c (working copy) @@ -0,0 +1,18 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power7" } */ + +/* This test should succeed on both 32- and 64-bit configurations. */ +#include <altivec.h> + +/* Test for the byte atomic operations on power8 using lbarx/stbcx. */ +__attribute__((target("cpu=power8"))) +char +char_fetch_add_relaxed (char *ptr, int value) +{ + return __atomic_fetch_add (ptr, value, __ATOMIC_RELAXED); +} + +/* { dg-final { scan-assembler-times "lbarx" 1 } } */ Index: gcc/testsuite/gcc.target/powerpc/pr78056-4.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-4.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-4.c (revision 243042) @@ -0,0 +1,20 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ +/* powerpc_vsx_ok represents power7 */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-skip-if "" { powerpc_p8vector_ok } } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power7" } */ + +/* This test should succeed on both 32- and 64-bit configurations. */ +#include <altivec.h> + +/* Though the command line specifies power7 target, this function is + to support power8, which will fail because this platform does not + support power8. */ +__attribute__((target("cpu=power8"))) +char +char_fetch_add_relaxed (char *ptr, int value) +{ /* { dg-warning "lacks power8 support" } */ + return __atomic_fetch_add (ptr, value, __ATOMIC_RELAXED); +} Index: gcc/testsuite/gcc.target/powerpc/pr78056-5.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-5.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-5.c (working copy) @@ -0,0 +1,17 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power5" } } */ +/* powerpc_vsx_ok represents power7 */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power5" } */ + +/* Though the command line specifies power5 target, this function is + to support power7. */ +__attribute__((target("cpu=power7"))) +int +div_we (int a, int b) +{ + return __builtin_divwe (a, b); +} + +/* { dg-final { scan-assembler-times "divwe " 1 } } */ Index: gcc/testsuite/gcc.target/powerpc/pr78056-6.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-6.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-6.c (working copy) @@ -0,0 +1,26 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */ +/* dfp_hw represents power 6 */ +/* { dg-require-effective-target dfp_hw } */ +/* powerpc_vsx_ok represents power7 */ +/* { dg-skip-if "" { powerpc_vsx_ok } } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power6" } */ + +/* This test should succeed on both 32- and 64-bit configurations. */ +#include <altivec.h> + +/* This test follows the pattern of pr78056-2.c, which has been + * exercised with binutils 2.25. This test, however, has not + * been exercised because the author of the test does not have access + * to a development environment that succesfully bootstraps gcc + * while at the same lacking assembler support for power 7. */ + +/* Though the command line specifies power6 target, this function is + to support power7. */ +__attribute__((target("cpu=power7"))) +int +div_we (int a, int b) +{ /* { dg-warning "lacks power7 support" } */ + return __builtin_divwe (a, b); /* { dg-warning "implicit declaration" } */ +} Index: gcc/testsuite/gcc.target/powerpc/pr78056-7.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-7.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-7.c (working copy) @@ -0,0 +1,15 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power5" } } */ +/* dfp_hw represents power 6 */ +/* { dg-require-effective-target dfp_hw } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power5" } */ + +/* Though the command line specifies power5 target, this function is + to support power6. */ +__attribute__((target("cpu=power6"))) +double power6 (double a, double b) +{ + return __builtin_copysign (a, b); +} +/* { dg-final { scan-assembler-times "fcpsgn" 1 } } */ Index: gcc/testsuite/gcc.target/powerpc/pr78056-8.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78056-8.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78056-8.c (working copy) @@ -0,0 +1,29 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power5" } } */ + +/* It is desirable to require-effective-target to be p5_ok, but there's + no such effective target, so we're just assuming that the effective + target is at minimum power5 ok. This test will fail if the + effective target is not power 5 ok, but there is no dg directive to + "unsupport" this test on such a platform. */ +/* dfp_hw represents support for power 6. */ +/* { dg-skip-if "" { dfp_hw } } */ +/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-options "-mcpu=power5" } */ + +/* This test follows the pattern of pr78056-2.c, which has been + * exercised with binutils 2.25. This test, however, has not + * been exercised because the author of the test does not have access + * to a development environment that succesfully bootstraps gcc + * while at the same lacking assembler support for power 6. */ + +/* This test should succeed on both 32- and 64-bit configurations. */ +/* Though the command line specifies power5 target, this function is + to support power6. Expect an error message here because this target + does not support power6. */ +__attribute__((target("cpu=power6"))) +/* fabs/fnabs/fsel */ +double normal1 (double a, double b) +{ /* { dg-warning "lacks power6 support" } */ + return __builtin_copysign (a, b); /* { dg-warning "implicit declaration" } */ +}