[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