[PATCH] RISC-V: Use tp as gp when no TLS is used.
Die Li
lidie@eswincomputing.com
Thu Aug 3 11:51:07 GMT 2023
This patch extends the GP-relative addressing mode by adding a 4K address
range on top of GP+2k, using the TP register instead of GP for relative
addressing. This allows more data to benefit from the relative addressing
access mode. As TP register is used for this optimization, it checks for
the presence of TLS (Thread-Local Storage) sections to ensure that the
optimization is performed only when TP is available. Additionally, a linker
option, "--tp-as-gp", is introduced to control the enabling of this optimization.
Take the "tp_as_gp.s" from this patch as an example to illustrate its optimization effect:
Before this patch:
After assembling and processing with "--relax", we have:
00000000000100e8 <_start>:
100e8: 67c5 lui a5,0x11
100ea: 0f878793 add a5,a5,248 # 110f8 <global_array>
100ee: 67c9 lui a5,0x12
100f0: 6d878793 add a5,a5,1752 # 126d8 <global_array2>
With this patch:
After assembling and processing with "--relax --tp-as-gp", we have:
00000000000100e8 <_start>:
100e8: 67c5 lui a5,0x11
100ea: 0f878793 add a5,a5,248 # 110f8 <global_array>
100ee: de620793 add a5,tp,-538 # .*
Check the symbol table, we have:
6: 00000000000118f4 0 NOTYPE GLOBAL DEFAULT ABS __global_pointer$
The addressable range of TP is increased by 4K beyond the addressable range of GP,
thus setting TP to GP+0x1000. So the access to global_array2, which was originally
represented as "lui a5,0x12" followed by "add a5,a5,1752 # 126d8", is optimized to
"add a5,tp,-538", which is feasible.
Signed-off-by: Die Li <lidie@eswincomputing.com>
ChangeLog:
* bfd/elfnn-riscv.c (tpoff):
(_bfd_riscv_relax_lui): Convert R_RISCV_HI20 to R_RISCV_TPREL_HI20,
R_RISCV_LO12_I to R_RISCV_TPREL_LO12_I,
R_RISCV_LO12_S to R_RISCV_TPREL_LO12_S
when use tp as gp.
* ld/ldlex.h (enum option_values): Add OPTION_RELAX_TP_AS_GP.
* ld/ldmain.c (main): Add option state.
* ld/ldmain.h (ENABLE_TP_AS_GP): New macro to control option.
* ld/lexsup.c (parse_args): Add --tp-as-gp option.
* ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add test entry.
* ld/testsuite/ld-riscv-elf/tp_as_gp.d: New test.
* ld/testsuite/ld-riscv-elf/tp_as_gp.s: New test.
include/ChangeLog:
* bfdlink.h (struct bfd_link_info): Clarify the option state.
* elf/riscv.h (ENABLE_TP_AS_GP): New macro relative with option.
(USED_TP_AS_GP): Likewise.
---
bfd/elfnn-riscv.c | 52 +++++++++++++++++-----
include/bfdlink.h | 6 +++
include/elf/riscv.h | 6 +++
ld/ldlex.h | 1 +
ld/ldmain.c | 1 +
ld/ldmain.h | 2 +
ld/lexsup.c | 5 +++
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 1 +
ld/testsuite/ld-riscv-elf/tp_as_gp.d | 14 ++++++
ld/testsuite/ld-riscv-elf/tp_as_gp.s | 33 ++++++++++++++
10 files changed, 110 insertions(+), 11 deletions(-)
create mode 100644 ld/testsuite/ld-riscv-elf/tp_as_gp.d
create mode 100644 ld/testsuite/ld-riscv-elf/tp_as_gp.s
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 09aa7be225e..9d418521839 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -1700,17 +1700,6 @@ dtpoff (struct bfd_link_info *info, bfd_vma address)
return address - elf_hash_table (info)->tls_sec->vma - DTP_OFFSET;
}
-/* Return the relocation value for a static TLS tp-relative relocation. */
-
-static bfd_vma
-tpoff (struct bfd_link_info *info, bfd_vma address)
-{
- /* If tls_sec is NULL, we should have signalled an error already. */
- if (elf_hash_table (info)->tls_sec == NULL)
- return 0;
- return address - elf_hash_table (info)->tls_sec->vma - TP_OFFSET;
-}
-
/* Return the global pointer's value, or 0 if it is not in use. */
static bfd_vma
@@ -1725,6 +1714,25 @@ riscv_global_pointer_value (struct bfd_link_info *info)
return h->u.def.value + sec_addr (h->u.def.section);
}
+/* Return the relocation value for a static TLS tp-relative relocation. */
+
+static bfd_vma
+tpoff (struct bfd_link_info *info, bfd_vma address)
+{
+ /* If tls_sec is NULL, we try to use tp as gp, otherwise signal an error. */
+ if (elf_hash_table (info)->tls_sec == NULL)
+ {
+ if (info->tp_as_gp & USED_TP_AS_GP)
+ {
+ bfd_vma gp = riscv_global_pointer_value (info);
+ bfd_vma tp = gp + 0x1000;
+ return address - tp;
+ }
+ return 0;
+ }
+ return address - elf_hash_table (info)->tls_sec->vma - TP_OFFSET;
+}
+
/* Emplace a static relocation. */
static bfd_reloc_status_type
@@ -4657,6 +4665,28 @@ _bfd_riscv_relax_lui (bfd *abfd,
}
}
+ unsigned sym = ELFNN_R_SYM (rel->r_info);
+ if ((link_info->tp_as_gp & ENABLE_TP_AS_GP)
+ && (elf_hash_table (link_info)->tls_sec == NULL))
+ {
+ bfd_vma tp = gp + 0x1000;
+ if (undefined_weak
+ || VALID_ITYPE_IMM (symval)
+ || (symval >= tp
+ && VALID_ITYPE_IMM (symval - tp + max_alignment + reserve_size))
+ || (symval < tp
+ && VALID_ITYPE_IMM (symval - tp - max_alignment - reserve_size)))
+ {
+ link_info->tp_as_gp |= USED_TP_AS_GP;
+ if (ELFNN_R_TYPE (rel->r_info) == R_RISCV_HI20)
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_TPREL_HI20);
+ if (ELFNN_R_TYPE (rel->r_info) == R_RISCV_LO12_I)
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_TPREL_LO12_I);
+ if (ELFNN_R_TYPE (rel->r_info) == R_RISCV_LO12_S)
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_TPREL_LO12_S);
+ }
+ }
+
/* Can we relax LUI to C.LUI? Alignment might move the section forward;
account for this assuming page alignment at worst. In the presence of
RELRO segment the linker aligns it by one page size, therefore sections
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 840790a298c..bf79035341d 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -557,6 +557,12 @@ struct bfd_link_info
/* TRUE if commonpagesize is set on command-line. */
unsigned int commonpagesize_is_set : 1;
+ /* Tri-state variable:
+ 0 => option --tp-as-gp is not specified by user.
+ 1 => option --tp-as-gp is specified by user, but not used.
+ 3 => option --tp-as-gp is specified by user, and has been used. */
+ unsigned int tp_as_gp: 2;
+
/* Char that may appear as the first char of a symbol, but should be
skipped (like symbol_leading_char) when looking up symbols in
wrap_hash. Used by PowerPC Linux for 'dot' symbols. */
diff --git a/include/elf/riscv.h b/include/elf/riscv.h
index 0aa8b3359c4..5dfe7aee00d 100644
--- a/include/elf/riscv.h
+++ b/include/elf/riscv.h
@@ -115,6 +115,12 @@ END_RELOC_NUMBERS (R_RISCV_max)
/* File uses the 32E base integer instruction. */
#define EF_RISCV_RVE 0x0008
+/* Enable the switch of option --tp-as-gp. */
+#define ENABLE_TP_AS_GP 0x1
+
+/* Use the switch of option --tp-as-gp. */
+#define USED_TP_AS_GP 0x2
+
/* The name of the global pointer symbol. */
#define RISCV_GP_SYMBOL "__global_pointer$"
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 87cac02141d..ebd9e6282fb 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -54,6 +54,7 @@ enum option_values
OPTION_OFORMAT,
OPTION_RELAX,
OPTION_NO_RELAX,
+ OPTION_RELAX_TP_AS_GP,
OPTION_NO_SYMBOLIC,
OPTION_RETAIN_SYMBOLS_FILE,
OPTION_RPATH,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 06ac2c64fa8..d5c8fa62687 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -339,6 +339,7 @@ main (int argc, char **argv)
link_info.combreloc = true;
link_info.strip_discarded = true;
link_info.prohibit_multiple_definition_absolute = false;
+ link_info.tp_as_gp = 0;
link_info.textrel_check = DEFAULT_LD_TEXTREL_CHECK;
link_info.emit_hash = DEFAULT_EMIT_SYSV_HASH;
link_info.emit_gnu_hash = DEFAULT_EMIT_GNU_HASH;
diff --git a/ld/ldmain.h b/ld/ldmain.h
index dda124b96e8..f03ea59daea 100644
--- a/ld/ldmain.h
+++ b/ld/ldmain.h
@@ -56,6 +56,8 @@ extern char *error_handling_script;
do { link_info.disable_target_specific_optimizations = 2; } while (0)
#define ENABLE_RELAXATION \
do { link_info.disable_target_specific_optimizations = 0; } while (0)
+#define ENABLE_TP_AS_GP \
+ do { link_info.tp_as_gp = true; } while (0)
extern void add_ysym (const char *);
extern void add_wrap (const char *);
diff --git a/ld/lexsup.c b/ld/lexsup.c
index fe8722313fe..eaa126475ba 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -457,6 +457,8 @@ static const struct ld_option ld_options[] =
'\0', NULL, N_("Reduce code size by using target specific optimizations"), TWO_DASHES },
{ {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
'\0', NULL, N_("Do not use relaxation techniques to reduce code size"), TWO_DASHES },
+ { {"tp-as-gp", no_argument, NULL, OPTION_RELAX_TP_AS_GP},
+ '\0', NULL, N_("Use tp as gp when there is no multithreaded scenario that requires the tp"), TWO_DASHES },
{ {"retain-symbols-file", required_argument, NULL,
OPTION_RETAIN_SYMBOLS_FILE},
'\0', N_("FILE"), N_("Keep only symbols listed in FILE"), TWO_DASHES },
@@ -1286,6 +1288,9 @@ parse_args (unsigned argc, char **argv)
case OPTION_RELAX:
ENABLE_RELAXATION;
break;
+ case OPTION_RELAX_TP_AS_GP:
+ ENABLE_TP_AS_GP;
+ break;
case OPTION_RETAIN_SYMBOLS_FILE:
add_keepsyms_file (optarg);
break;
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 947a266ba72..45a1d7e487e 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -124,6 +124,7 @@ if [istarget "riscv*-*-*"] {
run_dump_test "pcgp-relax-01"
run_dump_test "pcgp-relax-01-norelaxgp"
run_dump_test "pcgp-relax-02"
+ run_dump_test "tp_as_gp"
run_dump_test "c-lui"
run_dump_test "c-lui-2"
run_dump_test "disas-jalr"
diff --git a/ld/testsuite/ld-riscv-elf/tp_as_gp.d b/ld/testsuite/ld-riscv-elf/tp_as_gp.d
new file mode 100644
index 00000000000..51b2e141e63
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/tp_as_gp.d
@@ -0,0 +1,14 @@
+#source: tp_as_gp.s
+#as:
+#ld: --relax --tp-as-gp
+#objdump: -d
+
+
+.*:[ ]+file format .*
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[ ]+[0-9a-f]+[ ]+lui[ ]+a5,.*
+.*:[ ]+[0-9a-f]+[ ]+add[ ]+a5,a5,[0-9]+ # [0-9a-f]+ <global_array>
+.*:[ ]+[0-9a-f]+[ ]+add[ ]+a5,tp,\-[0-9]+ # [0-9a-f]+ .*
\ No newline at end of file
diff --git a/ld/testsuite/ld-riscv-elf/tp_as_gp.s b/ld/testsuite/ld-riscv-elf/tp_as_gp.s
new file mode 100644
index 00000000000..6d723b6a14b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/tp_as_gp.s
@@ -0,0 +1,33 @@
+ .option nopic
+ .attribute arch, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0"
+ .attribute unaligned_access, 0
+ .attribute stack_align, 16
+ .text
+
+ .globl global_array
+ .bss
+ .align 3
+ .type global_array, @object
+ .size global_array, 5600
+global_array:
+ .zero 5600
+
+ .globl global_array2
+ .bss
+ .align 3
+ .type global_array3, @object
+ .size global_array3, 200
+global_array2:
+ .zero 200
+
+ .text
+ .align 1
+ .globl _start
+ .type _start, @function
+_start:
+ lui a5,%hi(global_array)
+ addi a5,a5,%lo(global_array)
+
+ lui a5,%hi(global_array2)
+ addi a5,a5,%lo(global_array2)
+
--
2.17.1
More information about the Binutils
mailing list