Some chips (such as SiWx917 from Silicon Labs) have slow data bus
access. The -mslow-flash-data option generates appropriate code for
these chips by disabling literal pools. However, the current
implementation completely prevents TLS (Thread Local Storage) variables
from working, since ARM does not provide relocations to encode TLS
variables directly into instructions - they require literal pools.

This change relaxes the -mslow-flash-data constraint to allow literal
pools specifically for TLS accesses. While this results in slower TLS
access (hence a warning is emitted), it is preferable to a hard error
that prevents TLS usage entirely.

With -mpure-code, literal pools remain completely disabled and TLS
access still results in an error.

Signed-off-by: Jérôme Pouiller <[email protected]>
---
 gcc/config/arm/arm.cc | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index a8ab7a4fb82..ff99b3aafb5 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -8704,6 +8704,19 @@ arm_legitimate_address_outer_p (machine_mode mode, rtx 
x, RTX_CODE outer,
   return 0;
 }
 
+/* Return nonzero if literal pool is allowed for the constant X.
+   With -mslow-flash-data, literal pools are allowed specifically for TLS
+   access.  With -mpure-code, literal pools are never allowed.  */
+static int
+arm_literal_pool_allowed_p (rtx x)
+{
+  if (!arm_disable_literal_pool)
+    return 1;
+  if (target_slow_flash_data && tls_mentioned_p (x))
+    return 1;
+  return 0;
+}
+
 /* Return true if we can avoid creating a constant pool entry for x.  */
 static bool
 can_avoid_literal_pool_for_label_p (rtx x)
@@ -8723,8 +8736,9 @@ can_avoid_literal_pool_for_label_p (rtx x)
      (set (reg r0) (mem (reg r0))).
      No extra register is required, and (mem (reg r0)) won't cause the use
      of literal pools.  */
-  if (arm_disable_literal_pool && SYMBOL_REF_P (x)
-      && CONSTANT_POOL_ADDRESS_P (x))
+  if (SYMBOL_REF_P (x)
+      && CONSTANT_POOL_ADDRESS_P (x)
+      && !arm_literal_pool_allowed_p (get_pool_constant (x)))
     return 1;
   return 0;
 }
@@ -9093,7 +9107,7 @@ thumb1_legitimate_address_p (machine_mode mode, rtx x, 
int strict_p)
   else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
           && SYMBOL_REF_P (x)
           && CONSTANT_POOL_ADDRESS_P (x) && !flag_pic
-          && !arm_disable_literal_pool)
+          && arm_literal_pool_allowed_p (get_pool_constant (x)))
     return 1;
 
   /* This is PC relative data after arm_reorg runs.  */
@@ -9159,7 +9173,7 @@ thumb1_legitimate_address_p (machine_mode mode, rtx x, 
int strict_p)
           && GET_MODE_SIZE (mode) == 4
           && SYMBOL_REF_P (x)
           && CONSTANT_POOL_ADDRESS_P (x)
-          && !arm_disable_literal_pool
+          && arm_literal_pool_allowed_p (get_pool_constant (x))
           && ! (flag_pic
                 && symbol_mentioned_p (get_pool_constant (x))
                 && ! pcrel_constant_p (get_pool_constant (x))))
@@ -9695,10 +9709,11 @@ arm_tls_referenced_p (rtx x)
        {
          /* ARM currently does not provide relocations to encode TLS variables
             into AArch32 instructions, only data, so there is no way to
-            currently implement these if a literal pool is disabled.  */
-         if (arm_disable_literal_pool)
+            currently implement these if a literal pool is disabled.
+            With -mslow-flash-data, we allow TLS by using the literal pool.  */
+         if (target_pure_code)
            sorry ("accessing thread-local storage is not currently supported "
-                  "with %<-mpure-code%> or %<-mslow-flash-data%>");
+                  "with %<-mpure-code%>");
 
          return true;
        }
@@ -18264,7 +18279,7 @@ static void
 push_minipool_fix (rtx_insn *insn, HOST_WIDE_INT address, rtx *loc,
                   machine_mode mode, rtx value)
 {
-  gcc_assert (!arm_disable_literal_pool);
+  gcc_assert (arm_literal_pool_allowed_p (value));
   Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix));
 
   fix->insn = insn;
@@ -19602,7 +19617,7 @@ arm_reorg (void)
 
   /* Make sure we do not attempt to create a literal pool even though it should
      no longer be necessary to create any.  */
-  if (arm_disable_literal_pool)
+  if (target_pure_code)
     return ;
 
   minipool_fix_head = minipool_fix_tail = NULL;
-- 
2.47.3

Reply via email to