From: Wilco Dijkstra Date: Mon, 9 Feb 2026 19:01:19 +0000 (+0000) Subject: AArch64: Add PIC/PIE support to large model [PR 123791] X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=b4aa063fe4a4142544a0aad362ef45b2f23165ee;p=thirdparty%2Fgcc.git 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 --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 291e191f788..7b1dcbdbcfa 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 8e394231a4a..17051d7b2cd 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 134fd469b87..c5bc5154845 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 9de6fb6dc1a..8fc1b422a86 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 9de6fb6dc1a..8fc1b422a86 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" } } */