aarch64: unexpected result with -mgeneral-regs-only and sve [PR94678]
authorFei Yang <felix.yang@huawei.com>
Wed, 22 Apr 2020 17:24:59 +0000 (18:24 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 22 Apr 2020 17:24:59 +0000 (18:24 +0100)
As the two testcases for PR94678 show, -mgeneral-regs-only is handled
properly with SVE.  We should issue an error message instead of expanding
SVE builtin funtions when -mgeneral-regs-only option is specified.

The middle end should never try to use vector patterns when the vector
modes have been disabled by !have_regs_of_mode.  But it's still wrong
for the target to provide patterns that would inevitably lead to spill
failure due to lack of registers.  So we should also add check for
!TARGET_GENERAL_REGS_ONLY in TARGET_SVE and other SVE related macros.

2020-04-22  Felix Yang  <felix.yang@huawei.com>

gcc/
PR target/94678
* config/aarch64/aarch64.h (TARGET_SVE):
Add && !TARGET_GENERAL_REGS_ONLY.
(TARGET_SVE2): Add && TARGET_SVE.
(TARGET_SVE2_AES, TARGET_SVE2_BITPERM, TARGET_SVE2_SHA3,
TARGET_SVE2_SM4): Add && TARGET_SVE2.
* config/aarch64/aarch64-sve-builtins.h
(sve_switcher::m_old_general_regs_only): New member.
* config/aarch64/aarch64-sve-builtins.cc (check_required_registers):
New function.
(reported_missing_registers_p): New variable.
(check_required_extensions): Call check_required_registers before
return if all required extenstions are present.
(sve_switcher::sve_switcher): Save TARGET_GENERAL_REGS_ONLY in
m_old_general_regs_only and clear MASK_GENERAL_REGS_ONLY in
global_options.x_target_flags.
(sve_switcher::~sve_switcher): Set MASK_GENERAL_REGS_ONLY in
global_options.x_target_flags if m_old_general_regs_only is true.

gcc/testsuite/
PR target/94678
* gcc.target/aarch64/sve/acle/general/nosve_6.c: New test.

gcc/ChangeLog
gcc/config/aarch64/aarch64-sve-builtins.cc
gcc/config/aarch64/aarch64-sve-builtins.h
gcc/config/aarch64/aarch64.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_6.c [new file with mode: 0644]

index 3b9af1c..085135c 100644 (file)
@@ -1,3 +1,24 @@
+2020-04-22  Felix Yang  <felix.yang@huawei.com>
+
+       PR target/94678
+       * config/aarch64/aarch64.h (TARGET_SVE):
+       Add && !TARGET_GENERAL_REGS_ONLY.
+       (TARGET_SVE2): Add && TARGET_SVE.
+       (TARGET_SVE2_AES, TARGET_SVE2_BITPERM, TARGET_SVE2_SHA3,
+       TARGET_SVE2_SM4): Add && TARGET_SVE2.
+       * config/aarch64/aarch64-sve-builtins.h
+       (sve_switcher::m_old_general_regs_only): New member.
+       * config/aarch64/aarch64-sve-builtins.cc (check_required_registers):
+       New function.
+       (reported_missing_registers_p): New variable.
+       (check_required_extensions): Call check_required_registers before
+       return if all required extenstions are present.
+       (sve_switcher::sve_switcher): Save TARGET_GENERAL_REGS_ONLY in
+       m_old_general_regs_only and clear MASK_GENERAL_REGS_ONLY in
+       global_options.x_target_flags.
+       (sve_switcher::~sve_switcher): Set MASK_GENERAL_REGS_ONLY in
+       global_options.x_target_flags if m_old_general_regs_only is true.
+
 2020-04-22  Zackery Spytz  <zspytz@gmail.com>
 
        * doc/extend.exi: Add "free" to list of other builtin functions
index ca4a0eb..8511382 100644 (file)
@@ -558,6 +558,10 @@ static hash_table<registered_function_hasher> *function_table;
    when the required extension is disabled.  */
 static bool reported_missing_extension_p;
 
+/* True if we've already complained about attempts to use functions
+   which require registers that are missing.  */
+static bool reported_missing_registers_p;
+
 /* Record that TYPE is an ABI-defined SVE type that contains NUM_ZR SVE vectors
    and NUM_PR SVE predicates.  MANGLED_NAME, if nonnull, is the ABI-defined
    mangling of the type.  */
@@ -657,6 +661,29 @@ report_missing_extension (location_t location, tree fndecl,
   reported_missing_extension_p = true;
 }
 
+/* Check whether the registers required by SVE function fndecl are available.
+   Report an error against LOCATION and return false if not.  */
+static bool
+check_required_registers (location_t location, tree fndecl)
+{
+  /* Avoid reporting a slew of messages for a single oversight.  */
+  if (reported_missing_registers_p)
+    return false;
+
+  if (TARGET_GENERAL_REGS_ONLY)
+    {
+      /* SVE registers are not usable when -mgeneral-regs-only option
+        is specified.  */
+      error_at (location,
+               "ACLE function %qD is incompatible with the use of %qs",
+               fndecl, "-mgeneral-regs-only");
+      reported_missing_registers_p = true;
+      return false;
+    }
+
+  return true;
+}
+
 /* Check whether all the AARCH64_FL_* values in REQUIRED_EXTENSIONS are
    enabled, given that those extensions are required for function FNDECL.
    Report an error against LOCATION if not.  */
@@ -666,7 +693,7 @@ check_required_extensions (location_t location, tree fndecl,
 {
   uint64_t missing_extensions = required_extensions & ~aarch64_isa_flags;
   if (missing_extensions == 0)
-    return true;
+    return check_required_registers (location, fndecl);
 
   static const struct { uint64_t flag; const char *name; } extensions[] = {
 #define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
@@ -851,6 +878,9 @@ sve_switcher::sve_switcher ()
   aarch64_isa_flags = (AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16
                       | AARCH64_FL_SVE);
 
+  m_old_general_regs_only = TARGET_GENERAL_REGS_ONLY;
+  global_options.x_target_flags &= ~MASK_GENERAL_REGS_ONLY;
+
   memcpy (m_old_have_regs_of_mode, have_regs_of_mode,
          sizeof (have_regs_of_mode));
   for (int i = 0; i < NUM_MACHINE_MODES; ++i)
@@ -862,6 +892,8 @@ sve_switcher::~sve_switcher ()
 {
   memcpy (have_regs_of_mode, m_old_have_regs_of_mode,
          sizeof (have_regs_of_mode));
+  if (m_old_general_regs_only)
+    global_options.x_target_flags |= MASK_GENERAL_REGS_ONLY;
   aarch64_isa_flags = m_old_isa_flags;
 }
 
index f7f06d2..526d9f5 100644 (file)
@@ -658,6 +658,7 @@ public:
 
 private:
   unsigned long m_old_isa_flags;
+  bool m_old_general_regs_only;
   bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
 };
 
index 8f08bad..74236c3 100644 (file)
@@ -309,22 +309,22 @@ extern unsigned aarch64_architecture_version;
 #define TARGET_DOTPROD (TARGET_SIMD && AARCH64_ISA_DOTPROD)
 
 /* SVE instructions, enabled through +sve.  */
-#define TARGET_SVE (AARCH64_ISA_SVE)
+#define TARGET_SVE (!TARGET_GENERAL_REGS_ONLY && AARCH64_ISA_SVE)
 
 /* SVE2 instructions, enabled through +sve2.  */
-#define TARGET_SVE2 (AARCH64_ISA_SVE2)
+#define TARGET_SVE2 (TARGET_SVE && AARCH64_ISA_SVE2)
 
 /* SVE2 AES instructions, enabled through +sve2-aes.  */
-#define TARGET_SVE2_AES (AARCH64_ISA_SVE2_AES)
+#define TARGET_SVE2_AES (TARGET_SVE2 && AARCH64_ISA_SVE2_AES)
 
 /* SVE2 BITPERM instructions, enabled through +sve2-bitperm.  */
-#define TARGET_SVE2_BITPERM (AARCH64_ISA_SVE2_BITPERM)
+#define TARGET_SVE2_BITPERM (TARGET_SVE2 && AARCH64_ISA_SVE2_BITPERM)
 
 /* SVE2 SHA3 instructions, enabled through +sve2-sha3.  */
-#define TARGET_SVE2_SHA3 (AARCH64_ISA_SVE2_SHA3)
+#define TARGET_SVE2_SHA3 (TARGET_SVE2 && AARCH64_ISA_SVE2_SHA3)
 
 /* SVE2 SM4 instructions, enabled through +sve2-sm4.  */
-#define TARGET_SVE2_SM4 (AARCH64_ISA_SVE2_SM4)
+#define TARGET_SVE2_SM4 (TARGET_SVE2 && AARCH64_ISA_SVE2_SM4)
 
 /* ARMv8.3-A features.  */
 #define TARGET_ARMV8_3 (AARCH64_ISA_V8_3)
index b23a2dd..acd8b1a 100644 (file)
@@ -1,3 +1,8 @@
+2020-04-22  Felix Yang  <felix.yang@huawei.com>
+
+       PR target/94678
+       * gcc.target/aarch64/sve/acle/general/nosve_6.c: New test.
+
 2020-04-22  José Rui Faustino de Sousa  <jrfsousa@gmail.com>
 
        PR fortran/90350
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_6.c
new file mode 100644 (file)
index 0000000..d91ba40
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-options "-march=armv8-a -mgeneral-regs-only" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+#pragma GCC target "+sve"
+
+void
+f (svbool_t *x, svint8_t *y)
+{
+  *x = svptrue_b8 (); /* { dg-error {ACLE function '(svbool_t svptrue_b8\(\)|svptrue_b8)' is incompatible with the use of '-mgeneral-regs-only'} } */
+  *y = svadd_m (*x, *y, 1);
+}