Symbols with a large offset may be emitted into a literal pool.
aarch64_select_rtx_section() may then select .text or .rodata even if
the symbol has a dynamic relocation. Checking for CONST_INT or
CONST_DOUBLE avoids this. Ensure aarch64_cannot_force_const_mem()
returns true for symbols and labels so that they cannot be placed in
literal pools. Only the large code model emits symbols in the literal
pool (no support for PIC/PIE).
Passes regress, OK for commit?
gcc:
PR target/123791
* config/aarch64/aarch64.cc (aarch64_cannot_force_const_mem):
Always return true for symbols and labels except for large model.
(aarch64_select_rtx_section): Force .rodata for constants only.
gcc/testsuite:
PR target/123791
* gcc.target/aarch64/pr123791.c: New test.
---
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index
765c76165443e1829b0bf59e2956b1c5da476d04..b6ab1449ee4d73e9376043361d2738463e366f29
100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -11145,19 +11145,12 @@ 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). */
poly_int64 offset;
rtx base = strip_offset_and_salt (x, &offset);
- if (SYMBOL_REF_P (base) || LABEL_REF_P (base))
- {
- /* We checked for POLY_INT_CST offsets above. */
- if (aarch64_classify_symbol (base, offset.to_constant ())
- != SYMBOL_FORCE_TO_MEM)
- return true;
- else
- /* Avoid generating a 64-bit relocation in ILP32; leave
- to aarch64_expand_mov_immediate to handle it properly. */
- return mode != ptr_mode;
- }
+ if ((SYMBOL_REF_P (base) || LABEL_REF_P (base))
+ && aarch64_cmodel != AARCH64_CMODEL_LARGE)
+ return true;
return aarch64_tls_referenced_p (x);
}
@@ -14312,11 +14305,14 @@ 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);
/* When using anchors for constants use the readonly section. */
- if (known_le (GET_MODE_SIZE (mode), 8))
+ if ((CONST_INT_P (x) || CONST_DOUBLE_P (x))
+ && known_le (GET_MODE_SIZE (mode), 8))
return readonly_data_section;
return default_elf_select_rtx_section (mode, x, align);
diff --git a/gcc/testsuite/gcc.target/aarch64/pr123791.c
b/gcc/testsuite/gcc.target/aarch64/pr123791.c
new file mode 100644
index
0000000000000000000000000000000000000000..afdf37e8aac1a6451bb1375a32ab68f81b32b36c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr123791.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mpc-relative-literal-loads" } */
+
+char *
+foo ()
+{
+ return (char *) (__UINTPTR_TYPE__) foo + 7483647;
+}
+
+/* { dg-final { scan-assembler-not "\\.(word|xword)\tfoo" { xfail
aarch64_large } } } */