]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AArch64: Add PIC/PIE support to large model [PR 123791]
authorWilco Dijkstra <wilco.dijkstra@arm.com>
Mon, 9 Feb 2026 19:01:19 +0000 (19:01 +0000)
committerWilco Dijkstra <wilco.dijkstra@arm.com>
Thu, 21 May 2026 16:04:46 +0000 (16:04 +0000)
Use an indirection via GOT for data accesses that might be out of range of
ADRP.  Using the GOT avoids placing relro symbol references in literal pools
(PR 123791).  It also allows the large model to trivially support PIC/PIE.
Constants and readonly data use ADRP since the maximum text size is 2GB in
the large model [1].  The code quality of -mcmodel=large improves dramatically
as a result: codesize of SPEC2017 reduces by 2.2%.

[1] https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst#code-models

gcc:
PR target/123791
* config/aarch64/aarch64.cc (aarch64_cannot_force_const_mem): Remove
forcing symbol references to const mem.
(aarch64_can_use_per_function_literal_pools_p): Return false for
large model.
(aarch64_use_blocks_for_constant_p): Update comment.
(initialize_aarch64_code_model): Allow PIC/PIE.
(aarch64_classify_symbol): Use SYMBOL_SMALL_ABSOLUTE for constant
references and SYMBOL_SMALL_GOT_4G for writeable data.

gcc/testsuite:
PR target/123791
* gcc.target/aarch64/pr123791.c: Update test.
* gcc.target/aarch64/pr63304_1.c: Likewise.
* gcc.target/aarch64/pr78733.c: Likewise.
* gcc.target/aarch64/pr79041-2.c: Likewise.

gcc/config/aarch64/aarch64.cc
gcc/testsuite/gcc.target/aarch64/pr123791.c
gcc/testsuite/gcc.target/aarch64/pr63304_1.c
gcc/testsuite/gcc.target/aarch64/pr78733.c
gcc/testsuite/gcc.target/aarch64/pr79041-2.c

index 291e191f788ae299528e3d077aae67c8b67ff081..7b1dcbdbcfa20ea00d0d374050a3e60500f60301 100644 (file)
@@ -11184,11 +11184,10 @@ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
        || aarch64_sme_vq_unspec_p (x, &factor))
       return true;
 
-  /* Only allow symbols in literal pools with the large model (non-PIC).  */
+  /* Don't allow symbols in literal pools.  */
   poly_int64 offset;
   rtx base = strip_offset_and_salt (x, &offset);
-  if ((SYMBOL_REF_P (base) || LABEL_REF_P (base))
-      && aarch64_cmodel != AARCH64_CMODEL_LARGE)
+  if (SYMBOL_REF_P (base) || LABEL_REF_P (base))
     return true;
 
   return aarch64_tls_referenced_p (x);
@@ -14319,14 +14318,12 @@ aarch64_uxt_size (int shift, HOST_WIDE_INT mask)
 }
 
 /* Constant pools are per function only when PC relative
-   literal loads are true or we are in the large memory
-   model.  */
+   literal loads are true.  */
 
 static inline bool
 aarch64_can_use_per_function_literal_pools_p (void)
 {
-  return (aarch64_pcrelative_literal_loads
-         || aarch64_cmodel == AARCH64_CMODEL_LARGE);
+  return aarch64_pcrelative_literal_loads;
 }
 
 static bool
@@ -14345,8 +14342,6 @@ aarch64_select_rtx_section (machine_mode mode,
                            rtx x,
                            unsigned HOST_WIDE_INT align)
 {
-  /* Forcing special symbols into the .text section is not correct (PR123791).
-     This is only an issue with the large code model.  */
   if (aarch64_can_use_per_function_literal_pools_p ())
     return function_section (current_function_decl);
 
@@ -20363,9 +20358,6 @@ initialize_aarch64_code_model (struct gcc_options *opts)
   aarch64_cmodel = opts->x_aarch64_cmodel_var;
   if (aarch64_cmodel == AARCH64_CMODEL_LARGE)
     {
-      if (opts->x_flag_pic)
-       sorry ("code model %qs with %<-f%s%>", "large",
-              opts->x_flag_pic > 1 ? "PIC" : "pic");
       if (opts->x_aarch64_abi == AARCH64_ABI_ILP32)
        sorry ("code model %qs not supported in ilp32 mode", "large");
     }
@@ -22294,9 +22286,6 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
       if (aarch64_cmodel == AARCH64_CMODEL_TINY)
        return SYMBOL_TINY_ABSOLUTE;
 
-      if (aarch64_cmodel == AARCH64_CMODEL_LARGE)
-       return SYMBOL_FORCE_TO_MEM;
-
       return SYMBOL_SMALL_ABSOLUTE;
     }
 
@@ -22346,14 +22335,33 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
          return SYMBOL_SMALL_ABSOLUTE;
 
        case AARCH64_CMODEL_LARGE:
-         /* This is alright even in PIC code as the constant
-            pool reference is always PC relative and within
-            the same translation unit.  */
-         if (!aarch64_pcrelative_literal_loads && CONSTANT_POOL_ADDRESS_P (x))
-           return SYMBOL_SMALL_ABSOLUTE;
-         else
+         if (!TARGET_PECOFF
+             && (flag_pic || SYMBOL_REF_WEAK (x))
+             && !aarch64_symbol_binds_local_p (x))
+           return SYMBOL_SMALL_GOT_4G;
+
+         /* Read-only data uses ADRP/ADD, writable data uses the GOT.  */
+
+         if (!(IN_RANGE (offset, -0x100000, 0x100000)
+               || offset_within_block_p (x, offset)))
            return SYMBOL_FORCE_TO_MEM;
 
+         if (SYMBOL_REF_DECL (x) && TREE_READONLY (SYMBOL_REF_DECL (x)))
+           return SYMBOL_SMALL_ABSOLUTE;
+
+         if (CONSTANT_POOL_ADDRESS_P (x))
+           return SYMBOL_SMALL_ABSOLUTE;
+
+         if (SYMBOL_REF_HAS_BLOCK_INFO_P (x) && SYMBOL_REF_BLOCK (x) != NULL)
+           {
+             section *sect = SYMBOL_REF_BLOCK (x)->sect;
+
+             if (sect != NULL && !(sect->common.flags & SECTION_WRITE))
+               return SYMBOL_SMALL_ABSOLUTE;
+           }
+
+         return SYMBOL_SMALL_GOT_4G;
+
        default:
          gcc_unreachable ();
        }
index 8e394231a4a02dbb5bc1ad2a50775976c349593b..17051d7b2cdaa6b9477fb6ef2bb68ee791f28942 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -mpc-relative-literal-loads -Wno-deprecated" } */
+/* { dg-options "-O2" } */
 
 char *
 foo ()
@@ -7,4 +7,4 @@ foo ()
   return (char *) (__UINTPTR_TYPE__) foo + 7483647;
 }
 
-/* { dg-final { scan-assembler-not "\\.(word|xword)\tfoo" { xfail aarch64_large } } } */
+/* { dg-final { scan-assembler-not "\\.(word|xword)\tfoo" } } */
index 134fd469b87c265a189507c82b49f8ad08248e14..c5bc5154845cadefc2d15fcfbd0c38ef025d8bb9 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do assemble } */
 /* { dg-require-effective-target lp64 } */
-/* { dg-options "-O1 --save-temps -fno-pie" } */
+/* { dg-options "-O1 --save-temps" } */
 #pragma GCC push_options
 #pragma GCC target ("+nothing+simd,cmodel=small")
 
@@ -45,4 +45,4 @@ cal3 (double a)
     return 1;
 }
 
-/* { dg-final { scan-assembler-times "adrp" 4 } } */
+/* { dg-final { scan-assembler-times "adrp" 3 } } */
index 9de6fb6dc1ae3d7690ca41c9871a835eb4212476..8fc1b422a86616de4381ab10b8e9fb0b8c83b3de 100644 (file)
@@ -1,7 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads -fno-pie -Wno-deprecated" } */
+/* { dg-options "-O2 -mcmodel=large" } */
 /* { dg-require-effective-target lp64 } */
-/* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* }  { "-fpic" } { "" } } */
 
 __int128
 t (void)
@@ -9,5 +8,4 @@ t (void)
   return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321;
 }
 
-/* { dg-final { scan-assembler "adr" } } */
-/* { dg-final { scan-assembler-not "adrp" } } */
+/* { dg-final { scan-assembler "adrp" } } */
index 9de6fb6dc1ae3d7690ca41c9871a835eb4212476..8fc1b422a86616de4381ab10b8e9fb0b8c83b3de 100644 (file)
@@ -1,7 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads -fno-pie -Wno-deprecated" } */
+/* { dg-options "-O2 -mcmodel=large" } */
 /* { dg-require-effective-target lp64 } */
-/* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* }  { "-fpic" } { "" } } */
 
 __int128
 t (void)
@@ -9,5 +8,4 @@ t (void)
   return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321;
 }
 
-/* { dg-final { scan-assembler "adr" } } */
-/* { dg-final { scan-assembler-not "adrp" } } */
+/* { dg-final { scan-assembler "adrp" } } */