Hi Andrew, There are cases when an pic address gets complicated, and it needs to be resolved via force_reg function found in prepare_move_operands. When this happens, we need to disambiguate the pic address and re-legitimize it. Testcase added as well.
The patch needs to be applied to trunk and gcc9 branch as well. OK to apply? Claudiu gcc/ xxxx-xx-xx Claudiu Zissulescu <claz...@synopsys.com> * config/arc/arc.c (arc_legitimize_pic_address): Consider UNSPECs as well, if interesting recover the symbol and re-legitimize the pic address. gcc/testsuite/ xxxx-xx-xx Claudiu Zissulescu <claz...@synopsys.com> * gcc.target/arc/pic-2.c: New file. --- gcc/config/arc/arc.c | 16 ++++++++++++++++ gcc/testsuite/gcc.target/arc/pic-2.c | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 gcc/testsuite/gcc.target/arc/pic-2.c diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 8e9db4c652d..0e838910e9d 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -6234,6 +6234,22 @@ arc_legitimize_pic_address (rtx addr) switch (GET_CODE (addr)) { + case UNSPEC: + /* Can be one or our GOT or GOTOFFPC unspecs. This situation + happens when an address is not a legitimate constant and we + need the resolve it via force_reg in + prepare_move_operands. */ + switch (XINT (addr, 1)) + { + case ARC_UNSPEC_GOT: + case ARC_UNSPEC_GOTOFFPC: + /* Recover the symbol ref. */ + addr = XVECEXP (addr, 0, 0); + break; + default: + return addr; + } + /* Fall through. */ case SYMBOL_REF: /* TLS symbols are handled in different place. */ if (SYMBOL_REF_TLS_MODEL (addr)) diff --git a/gcc/testsuite/gcc.target/arc/pic-2.c b/gcc/testsuite/gcc.target/arc/pic-2.c new file mode 100644 index 00000000000..fed20e0a84c --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/pic-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-skip-if "PIC not available for ARC6xx" { arc6xx } } */ +/* { dg-options "-mno-sdata -O2 -fpic" } */ + +/* Check if we resolve correctly complex PIC addresses. */ + +char *foo (unsigned size) +{ + static char buf[32]; + register int i; + + if (size > 31) + size = 31; + + for (i = 0; i < size; i++) + { + buf[i] = ' '; + } + buf[size] = '\0'; + return buf; +} + +/* { dg-final { scan-assembler "@buf.\[0-9\]\+@pcl-1" } } */ -- 2.21.0