[lld] a05384d - [ELF] Make --no-relax disable R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 12 09:47:35 PST 2021
Author: Fangrui Song
Date: 2021-11-12T09:47:31-08:00
New Revision: a05384dc8930cbe967def7c5c4113740838e8fd0
URL: https://github.com/llvm/llvm-project/commit/a05384dc8930cbe967def7c5c4113740838e8fd0
DIFF: https://github.com/llvm/llvm-project/commit/a05384dc8930cbe967def7c5c4113740838e8fd0.diff
LOG: [ELF] Make --no-relax disable R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization
This brings back the original version of D81359.
I have found several use cases now.
* Unlike GNU ld, LLD's relocation processing is one pass. If we decide to
optimize(relax) R_X86_64_{,REX_}GOTPCRELX, we will suppress GOT generation and
cannot undo the decision later. Optimizing R_X86_64_REX_GOTPCRELX can usually
make it easy to hit `relocation R_X86_64_REX_GOTPCRELX out of range` because
the distance to GOT is usually shorter. Without --no-relax, the user has to
recompile with `-Wa,-mrelax-relocations=no`.
* The option would help during my investigationg of the root cause of https://git.kernel.org/linus/09e43968db40c33a73e9ddbfd937f46d5c334924
* There is need for relaxation for AArch64 & RISC-V. Implementing this for
x86-64 improves consistency with little target-specific cost (two-line
X86_64.cpp change).
Reviewed By: alexander-shaposhnikov
Differential Revision: https://reviews.llvm.org/D113615
Added:
Modified:
lld/ELF/Arch/X86_64.cpp
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/Options.td
lld/docs/ReleaseNotes.rst
lld/docs/ld.lld.1
lld/test/ELF/x86-64-gotpc-relax.s
Removed:
################################################################################
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index 4cb95d45bf02c..40436752399b4 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -802,8 +802,8 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
// with addend != -4. Such an instruction does not load the full GOT entry, so
// we cannot relax the relocation. E.g. movl x at GOTPCREL+4(%rip), %rax
// (addend=0) loads the high 32 bits of the GOT entry.
- if ((type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) ||
- addend != -4)
+ if (!config->relax || addend != -4 ||
+ (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX))
return R_GOT_PC;
const uint8_t op = loc[-2];
const uint8_t modRm = loc[-1];
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 65101d29136e2..79c4fe06d7b29 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -202,6 +202,7 @@ struct Configuration {
bool pie;
bool printGcSections;
bool printIcfSections;
+ bool relax;
bool relocatable;
bool relrPackDynRelocs;
bool saveTemps;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 14d740dfd8aca..9fac04558c461 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1115,6 +1115,7 @@ static void readConfigs(opt::InputArgList &args) {
config->printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
config->printSymbolOrder =
args.getLastArgValue(OPT_print_symbol_order);
+ config->relax = args.hasFlag(OPT_relax, OPT_no_relax, true);
config->rpath = getRpath(args);
config->relocatable = args.hasArg(OPT_relocatable);
config->saveTemps = args.hasArg(OPT_save_temps);
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 626b00c6c4e45..ce82eb8d27545 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -352,6 +352,10 @@ def push_state: F<"push-state">,
def print_map: F<"print-map">,
HelpText<"Print a link map to the standard output">;
+defm relax: BB<"relax",
+ "Enable target-specific relaxations if supported (default)",
+ "Disable target-specific relaxations">;
+
defm reproduce:
EEq<"reproduce",
"Write tar file containing inputs and command to reproduce link">;
@@ -695,7 +699,6 @@ def: F<"long-plt">;
def: F<"no-copy-dt-needed-entries">;
def: F<"no-ctors-in-init-array">;
def: F<"no-keep-memory">;
-def: F<"no-relax">;
def: F<"no-warn-mismatch">;
def: Separate<["--", "-"], "rpath-link">;
def: J<"rpath-link=">;
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index bd89cf0abf6f1..1d53177200c30 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -36,6 +36,9 @@ Architecture specific changes:
* The x86-32 port now supports TLSDESC (``-mtls-dialect=gnu2``).
(`D112582 <https://reviews.llvm.org/D112582>`_)
+* For x86-64, ``--no-relax`` now suppresses ``R_X86_64_GOTPCRELX`` and
+ ``R_X86_64_REX_GOTPCRELX`` GOT optimization
+ (`D113615 <https://reviews.llvm.org/D113615>`_)
Breaking changes
----------------
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index dda76c468d323..843f4a1cc2824 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -345,7 +345,7 @@ Page align sections.
.It Fl -no-omagic
Do not set the text data sections to be writable, page align sections.
.It Fl -no-relax
-Disable target-specific relaxations. This is currently a no-op.
+Disable target-specific relaxations. For x86-64 this disables R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization.
.It Fl -no-rosegment
Do not put read-only non-executable sections in their own segment.
.It Fl -no-undefined-version
diff --git a/lld/test/ELF/x86-64-gotpc-relax.s b/lld/test/ELF/x86-64-gotpc-relax.s
index bf10838fc524e..cfd17fdba4576 100644
--- a/lld/test/ELF/x86-64-gotpc-relax.s
+++ b/lld/test/ELF/x86-64-gotpc-relax.s
@@ -1,4 +1,6 @@
# REQUIRES: x86
+## Test R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization.
+
# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld %t.o -o %t1 --no-apply-dynamic-relocs
# RUN: llvm-readobj -x .got.plt -r %t1 | FileCheck --check-prefixes=RELOC,NO-APPLY-DYNAMIC-RELOCS %s
@@ -7,6 +9,10 @@
# RUN: ld.lld %t.o -o %t1
# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+## --no-relax disables GOT optimization.
+# RUN: ld.lld --no-relax %t.o -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=NORELAX %s
+
## There is one R_X86_64_IRELATIVE relocations.
# RELOC-LABEL: Relocations [
# RELOC-NEXT: Section (1) .rela.dyn {
@@ -60,6 +66,11 @@
# DISASM-NEXT: jmpq *4119(%rip)
# DISASM-NEXT: jmpq *4113(%rip)
+# NORELAX-LABEL: <_start>:
+# NORELAX-COUNT-12: movq
+# NORELAX-COUNT-6: callq *
+# NORELAX-COUNT-6: jmpq *
+
.text
.globl foo
.type foo, @function
More information about the llvm-commits
mailing list