https://gcc.gnu.org/g:b4aa063fe4a4142544a0aad362ef45b2f23165ee
commit r17-652-gb4aa063fe4a4142544a0aad362ef45b2f23165ee Author: Wilco Dijkstra <[email protected]> Date: Mon Feb 9 19:01:19 2026 +0000 AArch64: Add PIC/PIE support to large model [PR 123791] 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. Diff: --- gcc/config/aarch64/aarch64.cc | 50 ++++++++++++++++------------ gcc/testsuite/gcc.target/aarch64/pr123791.c | 4 +-- gcc/testsuite/gcc.target/aarch64/pr63304_1.c | 4 +-- gcc/testsuite/gcc.target/aarch64/pr78733.c | 6 ++-- gcc/testsuite/gcc.target/aarch64/pr79041-2.c | 6 ++-- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 291e191f788a..7b1dcbdbcfa2 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -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 (); } diff --git a/gcc/testsuite/gcc.target/aarch64/pr123791.c b/gcc/testsuite/gcc.target/aarch64/pr123791.c index 8e394231a4a0..17051d7b2cda 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr123791.c +++ b/gcc/testsuite/gcc.target/aarch64/pr123791.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c index 134fd469b87c..c5bc5154845c 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr78733.c b/gcc/testsuite/gcc.target/aarch64/pr78733.c index 9de6fb6dc1ae..8fc1b422a866 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr78733.c +++ b/gcc/testsuite/gcc.target/aarch64/pr78733.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c index 9de6fb6dc1ae..8fc1b422a866 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c @@ -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" } } */
