Commit 7d3b27ff by Wilco Dijkstra Committed by Wilco Dijkstra

[AArch64] Fix symbol offset limit

In aarch64_classify_symbol symbols are allowed large offsets on relocations. 
This means the offset can use all of the +/-4GB offset, leaving no offset
available for the symbol itself.  This results in relocation overflow and
link-time errors for simple expressions like &global_array + 0xffffff00.

To avoid this, unless the offset_within_block_p is true, limit the offset
to +/-1MB so that the symbol needs to be within a 3.9GB offset from its
references.  For the tiny code model use a 64KB offset, allowing most of
the 1MB range for code/data between the symbol and its references.

    gcc/
	* config/aarch64/aarch64.c (aarch64_classify_symbol):
	Apply reasonable limit to symbol offsets.

    testsuite/
	* gcc.target/aarch64/symbol-range.c: Improve testcase.
	* gcc.target/aarch64/symbol-range-tiny.c: Likewise.

From-SVN: r277068
parent aab8c2fd
2019-10-16 Wilco Dijkstra <wdijkstr@arm.com>
* config/aarch64/aarch64.c (aarch64_classify_symbol):
Apply reasonable limit to symbol offsets.
2019-10-16 Richard Biener <rguenther@suse.de> 2019-10-16 Richard Biener <rguenther@suse.de>
* tree-vect-loop.c (vect_valid_reduction_input_p): Remove. * tree-vect-loop.c (vect_valid_reduction_input_p): Remove.
......
...@@ -14122,26 +14122,31 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) ...@@ -14122,26 +14122,31 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
the offset does not cause overflow of the final address. But the offset does not cause overflow of the final address. But
we have no way of knowing the address of symbol at compile time we have no way of knowing the address of symbol at compile time
so we can't accurately say if the distance between the PC and so we can't accurately say if the distance between the PC and
symbol + offset is outside the addressible range of +/-1M in the symbol + offset is outside the addressible range of +/-1MB in the
TINY code model. So we rely on images not being greater than TINY code model. So we limit the maximum offset to +/-64KB and
1M and cap the offset at 1M and anything beyond 1M will have to assume the offset to the symbol is not larger than +/-(1MB - 64KB).
be loaded using an alternative mechanism. Furthermore if the If offset_within_block_p is true we allow larger offsets.
symbol is a weak reference to something that isn't known to Furthermore force to memory if the symbol is a weak reference to
resolve to a symbol in this module, then force to memory. */ something that doesn't resolve to a symbol in this module. */
if ((SYMBOL_REF_WEAK (x)
&& !aarch64_symbol_binds_local_p (x)) if (SYMBOL_REF_WEAK (x) && !aarch64_symbol_binds_local_p (x))
|| !IN_RANGE (offset, -1048575, 1048575))
return SYMBOL_FORCE_TO_MEM; return SYMBOL_FORCE_TO_MEM;
if (!(IN_RANGE (offset, -0x10000, 0x10000)
|| offset_within_block_p (x, offset)))
return SYMBOL_FORCE_TO_MEM;
return SYMBOL_TINY_ABSOLUTE; return SYMBOL_TINY_ABSOLUTE;
case AARCH64_CMODEL_SMALL: case AARCH64_CMODEL_SMALL:
/* Same reasoning as the tiny code model, but the offset cap here is /* Same reasoning as the tiny code model, but the offset cap here is
4G. */ 1MB, allowing +/-3.9GB for the offset to the symbol. */
if ((SYMBOL_REF_WEAK (x)
&& !aarch64_symbol_binds_local_p (x)) if (SYMBOL_REF_WEAK (x) && !aarch64_symbol_binds_local_p (x))
|| !IN_RANGE (offset, HOST_WIDE_INT_C (-4294967263),
HOST_WIDE_INT_C (4294967264)))
return SYMBOL_FORCE_TO_MEM; return SYMBOL_FORCE_TO_MEM;
if (!(IN_RANGE (offset, -0x100000, 0x100000)
|| offset_within_block_p (x, offset)))
return SYMBOL_FORCE_TO_MEM;
return SYMBOL_SMALL_ABSOLUTE; return SYMBOL_SMALL_ABSOLUTE;
case AARCH64_CMODEL_TINY_PIC: case AARCH64_CMODEL_TINY_PIC:
......
2019-10-16 Wilco Dijkstra <wdijkstr@arm.com>
* gcc.target/aarch64/symbol-range.c: Improve testcase.
* gcc.target/aarch64/symbol-range-tiny.c: Likewise.
2019-10-16 Richard Biener <rguenther@suse.de> 2019-10-16 Richard Biener <rguenther@suse.de>
* gcc.dg/vect/vect-cond-reduc-3.c: New testcase. * gcc.dg/vect/vect-cond-reduc-3.c: New testcase.
......
/* { dg-do compile } */ /* { dg-do link } */
/* { dg-options "-O3 -save-temps -mcmodel=tiny" } */ /* { dg-options "-O3 -save-temps -mcmodel=tiny" } */
int fixed_regs[0x00200000]; char fixed_regs[0x00080000];
int int
foo() main ()
{ {
return fixed_regs[0x00080000]; return fixed_regs[0x000ff000];
} }
/* { dg-final { scan-assembler-not "adr\tx\[0-9\]+, fixed_regs\\\+" } } */ /* { dg-final { scan-assembler-not "adr\tx\[0-9\]+, fixed_regs\\\+" } } */
/* { dg-do compile } */ /* { dg-do link } */
/* { dg-options "-O3 -save-temps -mcmodel=small" } */ /* { dg-options "-O3 -save-temps -mcmodel=small" } */
int fixed_regs[0x200000000ULL]; char fixed_regs[0x80000000];
int int
foo() main ()
{ {
return fixed_regs[0x100000000ULL]; return fixed_regs[0xfffff000];
} }
/* { dg-final { scan-assembler-not "adrp\tx\[0-9\]+, fixed_regs\\\+" } } */ /* { dg-final { scan-assembler-not "adrp\tx\[0-9\]+, fixed_regs\\\+" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment