https://gcc.gnu.org/g:c021c69e0de6ba01ecdb63cf8cad0813594b12ae
commit r17-620-gc021c69e0de6ba01ecdb63cf8cad0813594b12ae Author: Michiel Derhaeg <[email protected]> Date: Wed May 20 10:57:09 2026 +0300 arc: check if the addend fits when referencing small data memory [PR115650] This prevents linker errors when referencing small data using large offsets. In practice it is very unlikely to be a real problem but this was fixed because other compilers do this check and it ensures the following tests now succeed: - gcc.dg/torture/pr60115.c - gcc.dg/torture/pr105665.c gcc/ChangeLog: PR target/115650 * config/arc/arc.cc (legitimate_small_data_address_p): Check offset size. gcc/testsuite/ChangeLog: PR target/115650 * gcc.target/arc/sdata-6.c: New test. Signed-off-by: Michiel Derhaeg <[email protected]> Signed-off-by: Claudiu Zissulescu <[email protected]> Diff: --- gcc/config/arc/arc.cc | 30 +++++++++++++++------ gcc/testsuite/gcc.target/arc/sdata-6.c | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index a46741b08dc7..fd780ea0415f 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -386,27 +386,41 @@ legitimate_small_data_address_p (rtx x, machine_mode mode) return SYMBOL_REF_SMALL_P (x); case PLUS: { - bool p0 = (GET_CODE (XEXP (x, 0)) == SYMBOL_REF) - && SYMBOL_REF_SMALL_P (XEXP (x, 0)); + if ((GET_CODE (XEXP (x, 0)) != SYMBOL_REF) + || !SYMBOL_REF_SMALL_P (XEXP (x, 0))) + return false; /* If no constant then we cannot do small data. */ if (!CONST_INT_P (XEXP (x, 1))) return false; - /* Small data relocs works with scalled addresses, check if + const int offset = INTVAL (XEXP (x, 1)); + int size = GET_MODE_SIZE (mode); + size = size == 8 ? 4 : size; + + /* Small data relocs works with scaled addresses, check if the immediate fits the requirements. */ - switch (GET_MODE_SIZE (mode)) + switch (size) { case 1: - return p0; + break; case 2: - return p0 && ((INTVAL (XEXP (x, 1)) & 0x1) == 0); + if ((offset & 0x1) == 0) + break; + else + return false; case 4: - case 8: - return p0 && ((INTVAL (XEXP (x, 1)) & 0x3) == 0); + if ((offset & 0x3) == 0) + break; + else + return false; default: return false; } + + /* Reloc allows scaled signed 9 bits. */ + const int v = (offset / size) >> 8; + return v == 0 || v == -1; } default: return false; diff --git a/gcc/testsuite/gcc.target/arc/sdata-6.c b/gcc/testsuite/gcc.target/arc/sdata-6.c new file mode 100644 index 000000000000..2be261790a94 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/sdata-6.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msdata" } */ + +#include <stdint.h> + +__attribute__((section(".sdata"))) int a[300]; + +#define TEST(optype, threshold) \ + void consume##optype (int, int, int, int, optype); \ + optype test_r0_fit_##optype (void) { \ + return ((optype *)a)[threshold]; \ + } \ + optype test_r0_no_fit_##optype (void) \ + { \ + return ((optype *)a)[threshold + 1]; \ + } \ + void test_r4_fit_##optype (void) \ + { \ + return consume##optype (0, 0, 0, 0, ((optype *)a)[threshold]); \ + } \ + void test_r4_no_fit_##optype (void) \ + { \ + return consume##optype (0, 0, 0, 0, ((optype *)a)[threshold + 1]); \ + } + +TEST (char, 255) +TEST (short, 255) +TEST (int, 255) +TEST (int64_t, 127) + +/* { dg-final { scan-assembler "ldb_s\\s+r0,\\\[gp,@a@sda\\+255\\\]" } } */ +/* { dg-final { scan-assembler "ldb\\s+r0,\\\[@a\\+256\\\]" } } */ +/* { dg-final { scan-assembler "ldb\\s+r4,\\\[gp,@a@sda\\+255\\\]" } } */ +/* { dg-final { scan-assembler "ldb\\s+r4,\\\[@a\\+256\\\]" } } */ + +/* { dg-final { scan-assembler "ld\[hw\].x.as\\s+r0,\\\[gp,@a@sda\\+510\\\]" } } */ +/* { dg-final { scan-assembler "ld\[hw\].x\\s+r0,\\\[@a\\+512\\\]" } } */ +/* { dg-final { scan-assembler "ld\[hw\].x.as\\s+r4,\\\[gp,@a@sda\\+510\\\]" } } */ +/* { dg-final { scan-assembler "ld\[hw\].x\\s+r4,\\\[@a\\+512\\\]" } } */ + +/* { dg-final { scan-assembler "ld_s\\s+r0,\\\[gp,@a@sda\\+1020\\\]" } } */ +/* { dg-final { scan-assembler "ld\\s+r0,\\\[@a\\+1024\\\]" } } */ +/* { dg-final { scan-assembler "ld.as\\s+r4,\\\[gp,@a@sda\\+1020\\\]" } } */ +/* { dg-final { scan-assembler "ld\\s+r4,\\\[@a\\+1024\\\]" } } */ + +/* { dg-final { scan-assembler "ldd.as\\s+r0,\\\[gp,@a@sda\\+1016\\\]" { target ll64} } } */ +/* { dg-final { scan-assembler "ldd\\s+r0,\\\[@a\\+1024\\\]" { target ll64} } } */ +/* { dg-final { scan-assembler "ldd.as\\s+r4,\\\[gp,@a@sda\\+1016\\\]" { target ll64} } } */ +/* { dg-final { scan-assembler "ldd\\s+r4,\\\[@a\\+1024\\\]" { target ll64} } } */
