Jim Wilson
2018-10-15 23:01:37 UTC
For RISC-V, the compiler doesn't emit gp-relative references, they are created
during relaxation. Before this patch, the gp value is sdata+0x800 which is
guaranteed to cover as much as sdata+sbss as possible, but when they are
smaller than 0x1000 we end up wasting some of the gp-relative range. This
changes the calculation to shift gp down when possible, while still covering
all of sdata+sbss. This reduces code size for a trivial hello world program
by about 0.5%. For a more realistic benchmark set, EEMBC Automotive-1.1, I'm
seeing about 0.1% code size reduction on average. For large programs, this
has no effect.
This was tested with riscv{32,64}-{elf,linux} cross binutils build and check,
there were no regressions. I did have to update one linker testcase to disable
relaxation because it assumed that variable accesses in data would not be
relaxed. It was also tested with riscv32-elf and riscv64-linux cross gcc
build and check, and a linux+buildroot build and boot.
Committed.
Jim
ld/
* emulparams/elf32lriscv-defs.sh (DATA_START_SYMBOLS): New.
(SDATA_START_SYMBOLS): Define __SDATA_BEGIN__. Don't define
__global_pointer$.
(OTHER_END_SYMBOLS): New. Define __global_pointer$.
* testsuite/ld-riscv-elf/pcrel-lo-addend-2.d (#ld): Add --no-relax.
---
ld/emulparams/elf32lriscv-defs.sh | 13 ++++++++++++-
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d | 2 +-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/ld/emulparams/elf32lriscv-defs.sh b/ld/emulparams/elf32lriscv-defs.sh
index 91015d4471..5ac3b6023d 100644
--- a/ld/emulparams/elf32lriscv-defs.sh
+++ b/ld/emulparams/elf32lriscv-defs.sh
@@ -30,8 +30,19 @@ TEXT_START_ADDR=0x10000
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
-SDATA_START_SYMBOLS="${CREATE_SHLIB-__global_pointer$ = . + 0x800;}
+DATA_START_SYMBOLS="${CREATE_SHLIB-__DATA_BEGIN__ = .;}"
+
+SDATA_START_SYMBOLS="${CREATE_SHLIB-__SDATA_BEGIN__ = .;}
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)"
INITIAL_READONLY_SECTIONS=".interp : { *(.interp) } ${CREATE_PIE-${INITIAL_READONLY_SECTIONS}}"
INITIAL_READONLY_SECTIONS="${RELOCATING+${CREATE_SHLIB-${INITIAL_READONLY_SECTIONS}}}"
+
+# We must cover as much of sdata as possible if it exists. If sdata+bss is
+# smaller than 0x1000 then we should start from bss end to cover as much of
+# the program as possible. But we can't allow gp to cover any of rodata, as
+# the address of variables in rodata may change during relaxation, so we start
+# from data in that case.
+OTHER_END_SYMBOLS="${CREATE_SHLIB-__BSS_END__ = .;
+ __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
+ MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));}"
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
index 9e94c5c399..039de102c3 100644
--- a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
+++ b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
@@ -1,5 +1,5 @@
#name: %pcrel_lo overflow with an addend
#source: pcrel-lo-addend-2.s
#as: -march=rv32ic
-#ld: -melf32lriscv
+#ld: -melf32lriscv --no-relax
#error: .*dangerous relocation: %pcrel_lo overflow with an addend
during relaxation. Before this patch, the gp value is sdata+0x800 which is
guaranteed to cover as much as sdata+sbss as possible, but when they are
smaller than 0x1000 we end up wasting some of the gp-relative range. This
changes the calculation to shift gp down when possible, while still covering
all of sdata+sbss. This reduces code size for a trivial hello world program
by about 0.5%. For a more realistic benchmark set, EEMBC Automotive-1.1, I'm
seeing about 0.1% code size reduction on average. For large programs, this
has no effect.
This was tested with riscv{32,64}-{elf,linux} cross binutils build and check,
there were no regressions. I did have to update one linker testcase to disable
relaxation because it assumed that variable accesses in data would not be
relaxed. It was also tested with riscv32-elf and riscv64-linux cross gcc
build and check, and a linux+buildroot build and boot.
Committed.
Jim
ld/
* emulparams/elf32lriscv-defs.sh (DATA_START_SYMBOLS): New.
(SDATA_START_SYMBOLS): Define __SDATA_BEGIN__. Don't define
__global_pointer$.
(OTHER_END_SYMBOLS): New. Define __global_pointer$.
* testsuite/ld-riscv-elf/pcrel-lo-addend-2.d (#ld): Add --no-relax.
---
ld/emulparams/elf32lriscv-defs.sh | 13 ++++++++++++-
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d | 2 +-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/ld/emulparams/elf32lriscv-defs.sh b/ld/emulparams/elf32lriscv-defs.sh
index 91015d4471..5ac3b6023d 100644
--- a/ld/emulparams/elf32lriscv-defs.sh
+++ b/ld/emulparams/elf32lriscv-defs.sh
@@ -30,8 +30,19 @@ TEXT_START_ADDR=0x10000
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
-SDATA_START_SYMBOLS="${CREATE_SHLIB-__global_pointer$ = . + 0x800;}
+DATA_START_SYMBOLS="${CREATE_SHLIB-__DATA_BEGIN__ = .;}"
+
+SDATA_START_SYMBOLS="${CREATE_SHLIB-__SDATA_BEGIN__ = .;}
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)"
INITIAL_READONLY_SECTIONS=".interp : { *(.interp) } ${CREATE_PIE-${INITIAL_READONLY_SECTIONS}}"
INITIAL_READONLY_SECTIONS="${RELOCATING+${CREATE_SHLIB-${INITIAL_READONLY_SECTIONS}}}"
+
+# We must cover as much of sdata as possible if it exists. If sdata+bss is
+# smaller than 0x1000 then we should start from bss end to cover as much of
+# the program as possible. But we can't allow gp to cover any of rodata, as
+# the address of variables in rodata may change during relaxation, so we start
+# from data in that case.
+OTHER_END_SYMBOLS="${CREATE_SHLIB-__BSS_END__ = .;
+ __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
+ MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));}"
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
index 9e94c5c399..039de102c3 100644
--- a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
+++ b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
@@ -1,5 +1,5 @@
#name: %pcrel_lo overflow with an addend
#source: pcrel-lo-addend-2.s
#as: -march=rv32ic
-#ld: -melf32lriscv
+#ld: -melf32lriscv --no-relax
#error: .*dangerous relocation: %pcrel_lo overflow with an addend
--
2.17.1
2.17.1