https://github.com/fzou1 updated 
https://github.com/llvm/llvm-project/pull/136660

>From a98371ac23728289b7e1b9a1516141158bf7c1e0 Mon Sep 17 00:00:00 2001
From: Feng Zou <feng....@intel.com>
Date: Tue, 22 Apr 2025 11:05:29 +0800
Subject: [PATCH 1/2] [X86] Implement disabling APX relocations and EPGR/NDD
 instrs for them

Introduce an option (-mapx-relax-relocations) to control the emission of the
new APX relocations. It's off by default to keep backward compatibility with
older version of ld and other linkers without APX support. And EGPR and NDD are
also suppressed to avoid the instructions updated incorrectly by older version
of linker.
---
 clang/CMakeLists.txt                          |   3 +
 clang/cmake/caches/Fuchsia-stage2.cmake       |   1 +
 clang/cmake/caches/Fuchsia.cmake              |   1 +
 clang/include/clang/Basic/CodeGenOptions.def  |   1 +
 clang/include/clang/Config/config.h.cmake     |   3 +
 clang/include/clang/Driver/Options.td         |   3 +
 clang/include/clang/Driver/ToolChain.h        |   3 +
 clang/lib/CodeGen/BackendUtil.cpp             |   1 +
 clang/lib/Driver/ToolChain.cpp                |   4 +
 clang/lib/Driver/ToolChains/Clang.cpp         |  10 ++
 clang/test/Driver/relax.s                     |  15 +-
 clang/tools/driver/cc1as_main.cpp             |   5 +
 lld/ELF/Arch/X86_64.cpp                       |   6 +-
 lld/test/ELF/tls-opt.s                        | 111 ++++++++++----
 lld/test/ELF/x86-64-gotpc-no-relax-err.s      |   9 +-
 lld/test/ELF/x86-64-gotpc-relax-nopic.s       |  35 +++--
 lld/test/ELF/x86-64-gotpc-relax.s             |  91 +++++++----
 lld/test/ELF/x86-64-tlsdesc-gd.s              |  37 ++++-
 llvm/include/llvm/MC/MCTargetOptions.h        |   2 +
 .../llvm/MC/MCTargetOptionsCommandFlags.h     |   2 +
 llvm/lib/LTO/LTO.cpp                          |   1 +
 llvm/lib/MC/MCTargetOptionsCommandFlags.cpp   |  10 ++
 llvm/lib/Target/X86/CMakeLists.txt            |   1 +
 .../lib/Target/X86/MCTargetDesc/X86BaseInfo.h |  22 +++
 .../X86/MCTargetDesc/X86ELFObjectWriter.cpp   |  20 ++-
 llvm/lib/Target/X86/X86.h                     |   1 +
 llvm/lib/Target/X86/X86InstrInfo.cpp          |  17 +-
 .../X86/X86SuppressEGPRAndNDDForReloc.cpp     | 145 ++++++++++++++++++
 llvm/lib/Target/X86/X86TargetMachine.cpp      |   2 +
 llvm/test/CodeGen/X86/O0-pipeline.ll          |   1 +
 llvm/test/CodeGen/X86/apx/tls-desc.ll         |  96 ++++++++++++
 llvm/test/CodeGen/X86/opt-pipeline.ll         |   3 +
 llvm/test/MC/ELF/relocation-alias.s           |   8 +-
 llvm/test/MC/X86/elf-reloc-tls.s              |  16 +-
 llvm/test/MC/X86/gotpcrelx.s                  |  49 +++++-
 llvm/test/MC/X86/tlsdesc-64.s                 |   8 +-
 llvm/tools/gold/gold-plugin.cpp               |   2 +
 37 files changed, 635 insertions(+), 110 deletions(-)
 create mode 100644 llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp
 create mode 100644 llvm/test/CodeGen/X86/apx/tls-desc.ll

diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index c3f30e2a8e9c0..fa3063d6be9a7 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -219,6 +219,9 @@ set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id 
to ld")
 set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL
     "enable x86 relax relocations by default")
 
+set(ENABLE_X86_APX_RELAX_RELOCATIONS OFF CACHE BOOL
+    "Enable x86 APX relax relocations by default")
+
 set(PPC_LINUX_DEFAULT_IEEELONGDOUBLE OFF CACHE BOOL
     "Enable IEEE binary128 as default long double format on PowerPC Linux.")
 
diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake 
b/clang/cmake/caches/Fuchsia-stage2.cmake
index 99890b8246ad7..22eef24b611a8 100644
--- a/clang/cmake/caches/Fuchsia-stage2.cmake
+++ b/clang/cmake/caches/Fuchsia-stage2.cmake
@@ -49,6 +49,7 @@ set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
 
 set(ENABLE_LINKER_BUILD_ID ON CACHE BOOL "")
 set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "")
+set(ENABLE_X86_APX_RELAX_RELOCATIONS OFF CACHE BOOL "")
 
 # TODO(#67176): relative-vtables doesn't play well with different default
 # visibilities. Making everything hidden visibility causes other complications
diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake
index 83336589da305..550d94d1ec6a5 100644
--- a/clang/cmake/caches/Fuchsia.cmake
+++ b/clang/cmake/caches/Fuchsia.cmake
@@ -89,6 +89,7 @@ set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
 
 set(ENABLE_LINKER_BUILD_ID ON CACHE BOOL "")
 set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "")
+set(ENABLE_X86_APX_RELAX_RELOCATIONS OFF CACHE BOOL "")
 
 set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
 set(LLVM_ENABLE_BACKTRACES ON CACHE BOOL "")
diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index c5990fb248689..875facd6cfc63 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -201,6 +201,7 @@ CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal 
Linkage symbols get u
 CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using 
profile information.
 CODEGENOPT(PPCUseFullRegisterNames, 1, 0) ///< Print full register names in 
assembly
 CODEGENOPT(X86RelaxRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no}
+CODEGENOPT(X86APXRelaxRelocations, 1, 0) ///< -Wa,-mrelax-relocations={yes,no}
 CODEGENOPT(X86Sse2Avx        , 1, 0)   ///< -Wa,-msse2avx
 
 /// When false, this attempts to generate code as if the result of an
diff --git a/clang/include/clang/Config/config.h.cmake 
b/clang/include/clang/Config/config.h.cmake
index 00c352b458c34..db7fc2ba45eaf 100644
--- a/clang/include/clang/Config/config.h.cmake
+++ b/clang/include/clang/Config/config.h.cmake
@@ -72,6 +72,9 @@
 /* enable x86 relax relocations by default */
 #cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS
 
+/* enable x86 APX relax relocations by default */
+#cmakedefine01 ENABLE_X86_APX_RELAX_RELOCATIONS
+
 /* Enable IEEE binary128 as default long double format on PowerPC Linux. */
 #cmakedefine01 PPC_LINUX_DEFAULT_IEEELONGDOUBLE
 
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 919c1c643d080..a3becf76a7671 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -7442,6 +7442,9 @@ def mmapsyms_implicit : Flag<["-"], "mmapsyms=implicit">,
 def mrelax_relocations_no : Flag<["-"], "mrelax-relocations=no">,
     HelpText<"Disable x86 relax relocations">,
     MarshallingInfoNegativeFlag<CodeGenOpts<"X86RelaxRelocations">>;
+def mapx_relax_relocations_yes : Flag<["-"], "mapx-relax-relocations=yes">,
+    HelpText<"Enable x86 APX relax relocations">,
+    MarshallingInfoNegativeFlag<CodeGenOpts<"X86APXRelaxRelocations">>;
 def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
   HelpText<"Save temporary labels in the symbol table. "
            "Note this may change .s semantics and shouldn't generally be used "
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index d0059673d6a67..ef90956e25de0 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -473,6 +473,9 @@ class ToolChain {
   /// Check whether to enable x86 relax relocations by default.
   virtual bool useRelaxRelocations() const;
 
+  /// Check whether to enable x86 APX relax relocations by default.
+  virtual bool useAPXRelaxRelocations() const;
+
   /// Check whether use IEEE binary128 as long double format by default.
   bool defaultToIEEELongDouble() const;
 
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index f7eb853beb23c..72643631f39fc 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -513,6 +513,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
   Options.MCOptions.Crel = CodeGenOpts.Crel;
   Options.MCOptions.ImplicitMapSyms = CodeGenOpts.ImplicitMapSyms;
   Options.MCOptions.X86RelaxRelocations = CodeGenOpts.X86RelaxRelocations;
+  Options.MCOptions.X86APXRelaxRelocations = 
CodeGenOpts.X86APXRelaxRelocations;
   Options.MCOptions.CompressDebugSections =
       CodeGenOpts.getCompressDebugSections();
   if (CodeGenOpts.OutputAsmVariant != 3) // 3 (default): not specified
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 5cd5755e01587..c7bf259a678bd 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -192,6 +192,10 @@ bool ToolChain::useRelaxRelocations() const {
   return ENABLE_X86_RELAX_RELOCATIONS;
 }
 
+bool ToolChain::useAPXRelaxRelocations() const {
+  return ENABLE_X86_APX_RELAX_RELOCATIONS;
+}
+
 bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index f2f5231933c88..b1630dcca7306 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2602,6 +2602,8 @@ static void CollectArgsForIntegratedAssembler(Compilation 
&C,
   bool Crel = false, ExperimentalCrel = false;
   bool ImplicitMapSyms = false;
   bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations();
+  bool UseAPXRelaxRelocations =
+      C.getDefaultToolChain().useAPXRelaxRelocations();
   bool UseNoExecStack = false;
   bool Msa = false;
   const char *MipsTargetFeature = nullptr;
@@ -2663,6 +2665,12 @@ static void 
CollectArgsForIntegratedAssembler(Compilation &C,
           checkArg(IsELF, {"yes", "no"});
           continue;
         }
+        if (Equal.first == "-mapx-relax-relocations" ||
+            Equal.first == "--mapx-relax-relocations") {
+          UseAPXRelaxRelocations = Equal.second == "yes";
+          checkArg(IsELF, {"yes", "no"});
+          continue;
+        }
         if (Value == "-msse2avx") {
           CmdArgs.push_back("-msse2avx");
           continue;
@@ -2874,6 +2882,8 @@ static void CollectArgsForIntegratedAssembler(Compilation 
&C,
     CmdArgs.push_back("-mmsa");
   if (!UseRelaxRelocations)
     CmdArgs.push_back("-mrelax-relocations=no");
+  if (UseAPXRelaxRelocations)
+    CmdArgs.push_back("-mapx-relax-relocations=yes");
   if (UseNoExecStack)
     CmdArgs.push_back("-mnoexecstack");
   if (MipsTargetFeature != nullptr) {
diff --git a/clang/test/Driver/relax.s b/clang/test/Driver/relax.s
index 7b084de7e6be2..d3b58509f57bb 100644
--- a/clang/test/Driver/relax.s
+++ b/clang/test/Driver/relax.s
@@ -4,11 +4,20 @@
 // CHECK: "-cc1as"
 // CHECK: "-mrelax-relocations=no"
 
+// RUN: %clang -### -c --target=x86_64-pc-linux -integrated-as 
-Wa,--mapx-relax-relocations=yes %s 2>&1 | FileCheck %s 
--check-prefix=APXREL_OPTION
+
+// APXREL_OPTION: "-cc1as"
+// APXREL_OPTION: "-mapx-relax-relocations=yes"
+
+// RUN: %clang -cc1as -triple x86_64-pc-linux %s -o %t -filetype obj 
-mapx-relax-relocations=yes
+// RUN: llvm-readobj -r %t | FileCheck --check-prefix=APXREL %s
 // RUN: %clang -cc1as -triple x86_64-pc-linux %s -o %t -filetype obj
-// RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s
+// RUN: llvm-readobj -r %t | FileCheck --check-prefix=NOAPXREL %s
 
-// REL: R_X86_64_REX_GOTPCRELX foo
-// REL: R_X86_64_CODE_4_GOTPCRELX foo
+// APXREL: R_X86_64_REX_GOTPCRELX foo
+// APXREL: R_X86_64_CODE_4_GOTPCRELX foo
+// NOAPXREL: R_X86_64_REX_GOTPCRELX foo
+// NOAPXREL: R_X86_64_GOTPCREL foo
 
         movq   foo@GOTPCREL(%rip), %rax
         movq   foo@GOTPCREL(%rip), %r16
diff --git a/clang/tools/driver/cc1as_main.cpp 
b/clang/tools/driver/cc1as_main.cpp
index b98fc5ead100f..5654ea91f1349 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -171,6 +171,8 @@ struct AssemblerInvocation {
   LLVM_PREFERRED_TYPE(bool)
   unsigned X86RelaxRelocations : 1;
   LLVM_PREFERRED_TYPE(bool)
+  unsigned X86APXRelaxRelocations : 1;
+  LLVM_PREFERRED_TYPE(bool)
   unsigned X86Sse2Avx : 1;
 
   /// The name of the relocation model to use.
@@ -216,6 +218,7 @@ struct AssemblerInvocation {
     Crel = false;
     ImplicitMapsyms = 0;
     X86RelaxRelocations = 0;
+    X86APXRelaxRelocations = 0;
     X86Sse2Avx = 0;
   }
 
@@ -388,6 +391,7 @@ bool 
AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
   Opts.Crel = Args.hasArg(OPT_crel);
   Opts.ImplicitMapsyms = Args.hasArg(OPT_mmapsyms_implicit);
   Opts.X86RelaxRelocations = !Args.hasArg(OPT_mrelax_relocations_no);
+  Opts.X86APXRelaxRelocations = Args.hasArg(OPT_mapx_relax_relocations_yes);
   Opts.X86Sse2Avx = Args.hasArg(OPT_msse2avx);
 
   Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
@@ -449,6 +453,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
   MCOptions.Crel = Opts.Crel;
   MCOptions.ImplicitMapSyms = Opts.ImplicitMapsyms;
   MCOptions.X86RelaxRelocations = Opts.X86RelaxRelocations;
+  MCOptions.X86APXRelaxRelocations = Opts.X86APXRelaxRelocations;
   MCOptions.X86Sse2Avx = Opts.X86Sse2Avx;
   MCOptions.CompressDebugSections = Opts.CompressDebugSections;
   MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index 0c4fd00cab65c..28fdf4f0c8d80 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -912,9 +912,9 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, 
uint64_t val) const {
   case R_X86_64_CODE_4_GOTPC32_TLSDESC:
   case R_X86_64_TLSDESC_CALL:
   case R_X86_64_TLSGD:
-    if (rel.expr == R_RELAX_TLS_GD_TO_LE) {
+    if (rel.expr == R_RELAX_TLS_GD_TO_LE && ctx.arg.relax) {
       relaxTlsGdToLe(loc, rel, val);
-    } else if (rel.expr == R_RELAX_TLS_GD_TO_IE) {
+    } else if (rel.expr == R_RELAX_TLS_GD_TO_IE && ctx.arg.relax) {
       relaxTlsGdToIe(loc, rel, val);
     } else {
       checkInt(ctx, loc, val, 32, rel);
@@ -932,7 +932,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, 
uint64_t val) const {
   case R_X86_64_GOTTPOFF:
   case R_X86_64_CODE_4_GOTTPOFF:
   case R_X86_64_CODE_6_GOTTPOFF:
-    if (rel.expr == R_RELAX_TLS_IE_TO_LE) {
+    if (rel.expr == R_RELAX_TLS_IE_TO_LE && ctx.arg.relax) {
       relaxTlsIeToLe(loc, rel, val);
     } else {
       checkInt(ctx, loc, val, 32, rel);
diff --git a/lld/test/ELF/tls-opt.s b/lld/test/ELF/tls-opt.s
index 466dda0ef2e7b..cf8b46e088ddd 100644
--- a/lld/test/ELF/tls-opt.s
+++ b/lld/test/ELF/tls-opt.s
@@ -1,44 +1,84 @@
 // REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o 
-x86-apx-relax-relocations=true
 // RUN: ld.lld %t.o -o %t1
 // RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
-// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t1 | FileCheck 
--check-prefix=DISASM %s
+// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t1 | FileCheck 
--check-prefixes=DISASM,APXRELAX %s
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t1 --no-relax
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t1 | FileCheck 
--check-prefixes=DISASM,NOAPXRELAX %s
 
 // NORELOC:      Relocations [
 // NORELOC-NEXT: ]
 
 // DISASM:      <_start>:
-// DISASM-NEXT:   movq $-8, %rax
-// DISASM-NEXT:   movq $-8, %r15
-// DISASM-NEXT:   leaq -8(%rax), %rax
-// DISASM-NEXT:   leaq -8(%r15), %r15
-// DISASM-NEXT:   addq $-8, %rsp
-// DISASM-NEXT:   addq $-8, %r12
-// DISASM-NEXT:   movq $-4, %rax
-// DISASM-NEXT:   movq $-4, %r15
-// DISASM-NEXT:   leaq -4(%rax), %rax
-// DISASM-NEXT:   leaq -4(%r15), %r15
-// DISASM-NEXT:   addq $-4, %rsp
-// DISASM-NEXT:   addq $-4, %r12
+// APXRELAX-NEXT:   movq $-8, %rax
+// APXRELAX-NEXT:   movq $-8, %r15
+// APXRELAX-NEXT:   leaq -8(%rax), %rax
+// APXRELAX-NEXT:   leaq -8(%r15), %r15
+// APXRELAX-NEXT:   addq $-8, %rsp
+// APXRELAX-NEXT:   addq $-8, %r12
+// APXRELAX-NEXT:   movq $-4, %rax
+// APXRELAX-NEXT:   movq $-4, %r15
+// APXRELAX-NEXT:   leaq -4(%rax), %rax
+// APXRELAX-NEXT:   leaq -4(%r15), %r15
+// APXRELAX-NEXT:   addq $-4, %rsp
+// APXRELAX-NEXT:   addq $-4, %r12
+
+// NOAPXRELAX-NEXT:   movq -12(%rip), %rax
+// NOAPXRELAX-NEXT:   movq -12(%rip), %r15
+// NOAPXRELAX-NEXT:   addq -12(%rip), %rax
+// NOAPXRELAX-NEXT:   addq -12(%rip), %r15
+// NOAPXRELAX-NEXT:   addq -12(%rip), %rsp
+// NOAPXRELAX-NEXT:   addq -12(%rip), %r12
+// NOAPXRELAX-NEXT:   movq -8(%rip), %rax
+// NOAPXRELAX-NEXT:   movq -8(%rip), %r15
+// NOAPXRELAX-NEXT:   addq -8(%rip), %rax
+// NOAPXRELAX-NEXT:   addq -8(%rip), %r15
+// NOAPXRELAX-NEXT:   addq -8(%rip), %rsp
+// NOAPXRELAX-NEXT:   addq -8(%rip), %r12
+
 # EGPR
-// DISASM-NEXT:   movq $-8, %r16
-// DISASM-NEXT:   movq $-8, %r20
-// DISASM-NEXT:   movq $-4, %r16
-// DISASM-NEXT:   addq $-8, %r16
-// DISASM-NEXT:   addq $-8, %r28
-// DISASM-NEXT:   addq $-4, %r16
+// APXRELAX-NEXT:   movq $-8, %r16
+// APXRELAX-NEXT:   movq $-8, %r20
+// APXRELAX-NEXT:   movq $-4, %r16
+// APXRELAX-NEXT:   addq $-8, %r16
+// APXRELAX-NEXT:   addq $-8, %r28
+// APXRELAX-NEXT:   addq $-4, %r16
+
+// NOAPXRELAX-NEXT: movq -12(%rip), %r16
+// NOAPXRELAX-NEXT: movq -12(%rip), %r20
+// NOAPXRELAX-NEXT: movq -8(%rip), %r16
+// NOAPXRELAX-NEXT: addq -12(%rip), %r16
+// NOAPXRELAX-NEXT: addq -12(%rip), %r28
+// NOAPXRELAX-NEXT: addq -8(%rip), %r16
+
 # NDD
-// DISASM-NEXT:   addq $-8, %r16, %r16
-// DISASM-NEXT:   addq $-8, %r16, %r20
-// DISASM-NEXT:   addq $-8, %r16, %rax
-// DISASM-NEXT:   addq $-8, %rax, %r16
-// DISASM-NEXT:   addq $-8, %r8, %r16
-// DISASM-NEXT:   addq $-8, %rax, %r12
+// APXRELAX-NEXT:   addq $-8, %r16, %r16
+// APXRELAX-NEXT:   addq $-8, %r16, %r20
+// APXRELAX-NEXT:   addq $-8, %r16, %rax
+// APXRELAX-NEXT:   addq $-8, %rax, %r16
+// APXRELAX-NEXT:   addq $-8, %r8, %r16
+// APXRELAX-NEXT:   addq $-8, %rax, %r12
+
+// NOAPXRELAX-NEXT:   addq -12(%rip), %r16, %r16
+// NOAPXRELAX-NEXT:   addq -12(%rip), %r16, %r20
+// NOAPXRELAX-NEXT:   addq -12(%rip), %r16, %rax
+// NOAPXRELAX-NEXT:   addq -12(%rip), %rax, %r16
+// NOAPXRELAX-NEXT:   addq %r8, -12(%rip), %r16
+// NOAPXRELAX-NEXT:   addq -12(%rip), %rax, %r12
+
 # NDD + NF
-// DISASM-NEXT:   {nf} addq $-8, %r8, %r16
-// DISASM-NEXT:   {nf} addq $-8, %rax, %r12
+// APXRELAX-NEXT:   {nf} addq $-8, %r8, %r16
+// APXRELAX-NEXT:   {nf} addq $-8, %rax, %r12
+
+// NOAPXRELAX-NEXT:   {nf} addq %r8, -12(%rip), %r16
+// NOAPXRELAX-NEXT:   {nf} addq -12(%rip), %rax, %r12
+
 # NF
-// DISASM-NEXT:   {nf} addq $-8, %r12
+// APXRELAX-NEXT:   {nf} addq $-8, %r12
+// NOAPXRELAX-NEXT:   {nf} addq -12(%rip), %r12
 
 // LD to LE:
 // DISASM-NEXT:   movq %fs:0, %rax
@@ -47,10 +87,15 @@
 // DISASM-NEXT:   leaq -4(%rax), %rcx
 
 // GD to LE:
-// DISASM-NEXT:   movq %fs:0, %rax
-// DISASM-NEXT:   leaq -8(%rax), %rax
-// DISASM-NEXT:   movq %fs:0, %rax
-// DISASM-NEXT:   leaq -4(%rax), %rax
+// APXRELAX-NEXT:   movq %fs:0, %rax
+// APXRELAX-NEXT:   leaq -8(%rax), %rax
+// APXRELAX-NEXT:   movq %fs:0, %rax
+// APXRELAX-NEXT:   leaq -4(%rax), %rax
+
+// NOAPXRELAX-NEXT:   leaq -12(%rip), %rdi
+// NOAPXRELAX-NEXT:   callq 0x20126c
+// NOAPXRELAX-NEXT:   leaq -8(%rip), %rdi
+// NOAPXRELAX-NEXT:   callq 0x20127c
 
 // LD to LE:
 // DISASM:     <_DTPOFF64_1>:
diff --git a/lld/test/ELF/x86-64-gotpc-no-relax-err.s 
b/lld/test/ELF/x86-64-gotpc-no-relax-err.s
index 8452090e2c35a..c2628404a5516 100644
--- a/lld/test/ELF/x86-64-gotpc-no-relax-err.s
+++ b/lld/test/ELF/x86-64-gotpc-no-relax-err.s
@@ -1,7 +1,10 @@
 # REQUIRES: x86
 # RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o 
-x86-apx-relax-relocations=true
+# RUN: not ld.lld --no-relax -T %t/lds %t/a.o -o /dev/null 2>&1 | FileCheck %s 
--implicit-check-not=error: --check-prefixes=CHECK,APXRELAX
+
 # RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
-# RUN: not ld.lld --no-relax -T %t/lds %t/a.o -o /dev/null 2>&1 | FileCheck %s 
--implicit-check-not=error:
+# RUN: not ld.lld --no-relax -T %t/lds %t/a.o -o /dev/null 2>&1 | FileCheck %s 
--implicit-check-not=error: --check-prefixes=CHECK,NOAPXRELAX
 
 ## Test diagnostics for unrelaxed GOTPCRELX overflows. In addition, test that 
there is no
 ## `>>> defined in` for linker synthesized __stop_* symbols (there is no
@@ -13,9 +16,11 @@
 # CHECK-NEXT: error: {{.*}}:(.text+0x9): relocation R_X86_64_REX_GOTPCRELX out 
of range: 2147483659 is not in [-2147483648, 2147483647]; references 
'__stop_data'
 # CHECK-NEXT: >>> defined in <internal>
 # CHECK-EMPTY:
-# CHECK-NEXT: error: {{.*}}:(.text+0x11): relocation R_X86_64_CODE_4_GOTPCRELX 
out of range: 2147483651 is not in [-2147483648, 2147483647]; references 
'__stop_data'
+# APXRELAX-NEXT: error: {{.*}}:(.text+0x11): relocation 
R_X86_64_CODE_4_GOTPCRELX out of range: 2147483651 is not in [-2147483648, 
2147483647]; references '__stop_data'
+# NOAPXRELAX-NEXT: error: {{.*}}:(.text+0x11): relocation R_X86_64_GOTPCREL 
out of range: 2147483651 is not in [-2147483648, 2147483647]; references 
'__stop_data'
 # CHECK-NEXT: >>> defined in <internal>
 
+
 #--- a.s
   movl __stop_data@GOTPCREL(%rip), %eax  # out of range
   movq __stop_data@GOTPCREL(%rip), %rax  # out of range
diff --git a/lld/test/ELF/x86-64-gotpc-relax-nopic.s 
b/lld/test/ELF/x86-64-gotpc-relax-nopic.s
index be55c7d7006fe..67a155bfe0d76 100644
--- a/lld/test/ELF/x86-64-gotpc-relax-nopic.s
+++ b/lld/test/ELF/x86-64-gotpc-relax-nopic.s
@@ -1,8 +1,13 @@
 # REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o 
-x86-apx-relax-relocations=true
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj --symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s
+# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t1 | FileCheck 
--check-prefixes=DISASM,APXRELAX %s
+
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 # RUN: ld.lld %t.o -o %t1
 # RUN: llvm-readobj --symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s
-# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t1 | FileCheck 
--check-prefix=DISASM %s
+# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t1 | FileCheck 
--check-prefixes=DISASM,NOAPXRELAX %s
 
 ## There is no relocations.
 # SYMRELOC:      Relocations [
@@ -34,15 +39,25 @@
 # DISASM-NEXT:                 subq  $0x203290, %rbp
 # DISASM-NEXT:                 xorq  $0x203290, %r8
 # DISASM-NEXT:                 testq $0x203290, %r15
-# DISASM-NEXT:   20123f:       adcq  $0x203290, %r16
-# DISASM-NEXT:                 addq  $0x203290, %r17
-# DISASM-NEXT:                 andq  $0x203290, %r18
-# DISASM-NEXT:                 cmpq  $0x203290, %r19
-# DISASM-NEXT:                 orq   $0x203290, %r20
-# DISASM-NEXT:                 sbbq  $0x203290, %r21
-# DISASM-NEXT:                 subq  $0x203290, %r22
-# DISASM-NEXT:                 xorq  $0x203290, %r23
-# DISASM-NEXT:                 testq $0x203290, %r24
+# APXRELAX-NEXT:   20123f:       adcq  $0x203290, %r16
+# APXRELAX-NEXT:                 addq  $0x203290, %r17
+# APXRELAX-NEXT:                 andq  $0x203290, %r18
+# APXRELAX-NEXT:                 cmpq  $0x203290, %r19
+# APXRELAX-NEXT:                 orq   $0x203290, %r20
+# APXRELAX-NEXT:                 sbbq  $0x203290, %r21
+# APXRELAX-NEXT:                 subq  $0x203290, %r22
+# APXRELAX-NEXT:                 xorq  $0x203290, %r23
+# APXRELAX-NEXT:                 testq $0x203290, %r24
+
+# NOAPXRELAX-NEXT:   20123f:       adcq  0x1041(%rip), %r16
+# NOAPXRELAX-NEXT:                 addq  0x1039(%rip), %r17
+# NOAPXRELAX-NEXT:                 andq  0x1031(%rip), %r18
+# NOAPXRELAX-NEXT:                 cmpq  0x1029(%rip), %r19
+# NOAPXRELAX-NEXT:                 orq   0x1021(%rip), %r20
+# NOAPXRELAX-NEXT:                 sbbq  0x1019(%rip), %r21
+# NOAPXRELAX-NEXT:                 subq  0x1011(%rip), %r22
+# NOAPXRELAX-NEXT:                 xorq  0x1009(%rip), %r23
+# NOAPXRELAX-NEXT:                 testq  %r24, 0x1001(%rip)
 
 # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t2
 # RUN: llvm-readobj -S -r -d %t2 | FileCheck --check-prefix=SEC-PIC    %s
diff --git a/lld/test/ELF/x86-64-gotpc-relax.s 
b/lld/test/ELF/x86-64-gotpc-relax.s
index bc5830ba7b629..75b85db2abd14 100644
--- a/lld/test/ELF/x86-64-gotpc-relax.s
+++ b/lld/test/ELF/x86-64-gotpc-relax.s
@@ -1,13 +1,25 @@
 # REQUIRES: x86
 ## Test R_X86_64_GOTPCRELX and 
R_X86_64_REX_GOTPCRELX/R_X86_64_CODE_4_GOTPCRELX GOT optimization.
 
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o 
-x86-apx-relax-relocations=true
+# RUN: ld.lld %t.o -o %t1 --no-apply-dynamic-relocs
+# RUN: llvm-readelf -S -r -x .got.plt %t1 | FileCheck 
--check-prefixes=CHECK,APXRELAX,NOAPPLY-APXRELAX %s
+# RUN: ld.lld %t.o -o %t1 --apply-dynamic-relocs
+# RUN: llvm-readelf -S -r -x .got.plt %t1 | FileCheck 
--check-prefixes=CHECK,APPLY-APXRELAX %s
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-objdump --no-print-imm-hex -d %t1 | FileCheck 
--check-prefixes=DISASM,DISASM-APXRELAX %s
+
+## --no-relax disables GOT optimization.
+# RUN: ld.lld --no-relax %t.o -o %t2
+# RUN: llvm-objdump --no-print-imm-hex -d %t2 | FileCheck 
--check-prefix=NORELAX %s
+
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 # RUN: ld.lld %t.o -o %t1 --no-apply-dynamic-relocs
-# RUN: llvm-readelf -S -r -x .got.plt %t1 | FileCheck 
--check-prefixes=CHECK,NOAPPLY %s
+# RUN: llvm-readelf -S -r -x .got.plt %t1 | FileCheck 
--check-prefixes=CHECK,NOAPXRELAX,NOAPPLY-NOAPXRELAX %s
 # RUN: ld.lld %t.o -o %t1 --apply-dynamic-relocs
-# RUN: llvm-readelf -S -r -x .got.plt %t1 | FileCheck 
--check-prefixes=CHECK,APPLY %s
+# RUN: llvm-readelf -S -r -x .got.plt %t1 | FileCheck 
--check-prefixes=CHECK,APPLY-NOAPXRELAX %s
 # RUN: ld.lld %t.o -o %t1
-# RUN: llvm-objdump --no-print-imm-hex -d %t1 | FileCheck 
--check-prefix=DISASM %s
+# RUN: llvm-objdump --no-print-imm-hex -d %t1 | FileCheck 
--check-prefixes=DISASM,DISASM-NOAPXRELAX %s
 
 ## --no-relax disables GOT optimization.
 # RUN: ld.lld --no-relax %t.o -o %t2
@@ -16,15 +28,19 @@
 ## In our implementation, .got is retained even if all GOT-generating 
relocations are optimized.
 # CHECK:      Name              Type            Address          Off    Size   
ES Flg Lk Inf Al
 # CHECK:      .iplt             PROGBITS        00000000002012e0 0002e0 000010 
00  AX  0   0 16
-# CHECK-NEXT: .got              PROGBITS        00000000002022f0 0002f0 000000 
00  WA  0   0  8
+# APXRELAX-NEXT: .got              PROGBITS        00000000002022f0 0002f0 
000000 00  WA  0   0  8
+# NOAPXRELAX-NEXT: .got              PROGBITS        00000000002022f0 0002f0 
000010 00  WA  0   0  8
 
 ## There is one R_X86_64_IRELATIVE relocations.
 # RELOC-LABEL: Relocation section '.rela.dyn' at offset {{.*}} contains 1 
entry:
 # CHECK:           Offset             Info             Type               
Symbol's Value  Symbol's Name + Addend
-# CHECK:       00000000002032f0  0000000000000025 R_X86_64_IRELATIVE           
             2011e2
+# APXRELAX:       00000000002032f0  0000000000000025 R_X86_64_IRELATIVE        
                2011e2
+# NOAPXRELAX:       0000000000203300  0000000000000025 R_X86_64_IRELATIVE      
                  2011e2
 # CHECK-LABEL: Hex dump of section '.got.plt':
-# NOAPPLY-NEXT:  0x002032f0 00000000 00000000
-# APPLY-NEXT:    0x002032f0 e2112000 00000000
+# NOAPPLY-APXRELAX-NEXT:  0x002032f0 00000000 00000000
+# NOAPPLY-NOAPXRELAX-NEXT:  0x00203300 00000000 00000000
+# APPLY-APXRELAX-NEXT:    0x002032f0 e2112000 00000000
+# APPLY-NOAPXRELAX-NEXT:    0x00203300 e2112000 00000000
 
 # 0x201173 + 7 - 10 = 0x201170
 # 0x20117a + 7 - 17 = 0x201170
@@ -43,20 +59,26 @@
 # DISASM-NEXT: leaq -17(%rip), %rax
 # DISASM-NEXT: leaq -23(%rip), %rax
 # DISASM-NEXT: leaq -30(%rip), %rax
-# DISASM-NEXT: movq 8426(%rip), %rax
-# DISASM-NEXT: movq 8419(%rip), %rax
+# DISASM-APXRELAX-NEXT: movq 8426(%rip), %rax
+# DISASM-APXRELAX-NEXT: movq 8419(%rip), %rax
+# DISASM-NOAPXRELAX-NEXT: movq 8442(%rip), %rax
+# DISASM-NOAPXRELAX-NEXT: movq 8435(%rip), %rax
 # DISASM-NEXT: leaq -52(%rip), %rax
 # DISASM-NEXT: leaq -59(%rip), %rax
 # DISASM-NEXT: leaq -65(%rip), %rax
 # DISASM-NEXT: leaq -72(%rip), %rax
-# DISASM-NEXT: movq 8384(%rip), %rax
-# DISASM-NEXT: movq 8377(%rip), %rax
+# DISASM-APXRELAX-NEXT: movq 8384(%rip), %rax
+# DISASM-APXRELAX-NEXT: movq 8377(%rip), %rax
+# DISASM-NOAPXRELAX-NEXT: movq 8400(%rip), %rax
+# DISASM-NOAPXRELAX-NEXT: movq 8393(%rip), %rax
 # DISASM-NEXT: callq 0x2011e0 <foo>
 # DISASM-NEXT: callq 0x2011e0 <foo>
 # DISASM-NEXT: callq 0x2011e1 <hid>
 # DISASM-NEXT: callq 0x2011e1 <hid>
-# DISASM-NEXT: callq *8347(%rip)
-# DISASM-NEXT: callq *8341(%rip)
+# DISASM-APXRELAX-NEXT: callq *8347(%rip)
+# DISASM-APXRELAX-NEXT: callq *8341(%rip)
+# DISASM-NOAPXRELAX-NEXT: callq *8363(%rip)
+# DISASM-NOAPXRELAX-NEXT: callq *8357(%rip)
 # DISASM-NEXT: jmp   0x2011e0 <foo>
 # DISASM-NEXT: nop
 # DISASM-NEXT: jmp   0x2011e0 <foo>
@@ -65,20 +87,35 @@
 # DISASM-NEXT: nop
 # DISASM-NEXT: jmp   0x2011e1 <hid>
 # DISASM-NEXT: nop
-# DISASM-NEXT: jmpq  *8311(%rip)
-# DISASM-NEXT: jmpq  *8305(%rip)
-# DISASM-NEXT: leaq -167(%rip), %r16
-# DISASM-NEXT: leaq -175(%rip), %r16
-# DISASM-NEXT: leaq -182(%rip), %r16
-# DISASM-NEXT: leaq -190(%rip), %r16
-# DISASM-NEXT: movq 8265(%rip), %r16
-# DISASM-NEXT: movq 8257(%rip), %r16
-# DISASM-NEXT: leaq -215(%rip), %r16
-# DISASM-NEXT: leaq -223(%rip), %r16
-# DISASM-NEXT: leaq -230(%rip), %r16
-# DISASM-NEXT: leaq -238(%rip), %r16
-# DISASM-NEXT: movq 8217(%rip), %r16
-# DISASM-NEXT: movq 8209(%rip), %r16
+# DISASM-APXRELAX-NEXT: jmpq  *8311(%rip)
+# DISASM-APXRELAX-NEXT: jmpq  *8305(%rip)
+# DISASM-NOAPXRELAX-NEXT: jmpq *8327(%rip)
+# DISASM-NOAPXRELAX-NEXT: jmpq *8321(%rip)
+# DISASM-APXRELAX-NEXT: leaq -167(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -175(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -182(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -190(%rip), %r16
+# DISASM-APXRELAX-NEXT: movq 8265(%rip), %r16
+# DISASM-APXRELAX-NEXT: movq 8257(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -215(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -223(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -230(%rip), %r16
+# DISASM-APXRELAX-NEXT: leaq -238(%rip), %r16
+# DISASM-APXRELAX-NEXT: movq 8217(%rip), %r16
+# DISASM-APXRELAX-NEXT: movq 8209(%rip), %r16
+
+# DISASM-NOAPXRELAX-NEXT: movq 4201(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4193(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4193(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4185(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 8281(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 8273(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4153(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4145(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4145(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 4137(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 8233(%rip), %r16
+# DISASM-NOAPXRELAX-NEXT: movq 8225(%rip), %r16
 
 # NORELAX-LABEL: <_start>:
 # NORELAX-COUNT-12: movq
diff --git a/lld/test/ELF/x86-64-tlsdesc-gd.s b/lld/test/ELF/x86-64-tlsdesc-gd.s
index 433c2b2723463..4e2daea1d18b7 100644
--- a/lld/test/ELF/x86-64-tlsdesc-gd.s
+++ b/lld/test/ELF/x86-64-tlsdesc-gd.s
@@ -1,5 +1,5 @@
 # REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o 
-x86-apx-relax-relocations=true
 # RUN: echo '.tbss; .globl c; c: .zero 4' | llvm-mc -filetype=obj 
-triple=x86_64 - -o %t1.o
 # RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
 
@@ -18,6 +18,28 @@
 # RUN: llvm-readobj -r %t | FileCheck --check-prefix=IE-REL %s
 # RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck 
--check-prefix=IE %s
 
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: echo '.tbss; .globl c; c: .zero 4' | llvm-mc -filetype=obj 
-triple=x86_64 - -o %t1.o
+# RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
+
+# RUN: ld.lld -shared %t.o %t1.o -o %t.so
+# RUN: llvm-readobj -r -x .got %t.so | FileCheck --check-prefix=GD-RELA %s
+# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t.so | FileCheck 
--check-prefix=GD %s
+
+# RUN: ld.lld -shared %t.o %t1.o -o %t-rel.so -z rel
+# RUN: llvm-readobj -r -x .got %t-rel.so | FileCheck --check-prefix=GD-REL %s
+
+# RUN: ld.lld %t.o %t1.o -o %t
+# --no-relax
+# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
+# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck 
--check-prefix=LE_NOAPXRELAX %s
+
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=IE-REL %s
+# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck 
--check-prefix=IE %s
+
+
 # GD-RELA:      .rela.dyn {
 # GD-RELA-NEXT:   0x23E0 R_X86_64_TLSDESC - 0xB
 # GD-RELA-NEXT:   0x23C0 R_X86_64_TLSDESC a 0x0
@@ -78,10 +100,15 @@
 # LE-NEXT: nop
 # LE-NEXT: movl %fs:(%rax), %eax
 ## tpoff(c) = st_value(c) - tls_size = -4
-# LE:      movq $-4, %r16
-# LE-NEXT: movq %r16, %rax
-# LE-NEXT: nop
-# LE-NEXT: movl %fs:(%rax), %eax
+# LE_APXRELAX:      movq $-4, %r16
+# LE_APXRELAX-NEXT: movq %r16, %rax
+# LE_APXRELAX-NEXT: nop
+# LE_APXRELAX-NEXT: movl %fs:(%rax), %eax
+
+# LE_NOAPXRELAX:      movq $-4, %rax
+# LE_NOAPXRELAX-NEXT: movq %r16, %rax
+# LE_NOAPXRELAX-NEXT: nop
+# LE_NOAPXRELAX-NEXT: movl %fs:(%rax), %eax
 
 # IE-REL:      .rela.dyn {
 # IE-REL-NEXT:   0x202388 R_X86_64_TPOFF64 c 0x0
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h 
b/llvm/include/llvm/MC/MCTargetOptions.h
index fd554bc0ba7c6..52774975fbc70 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -70,6 +70,8 @@ class MCTargetOptions {
   // ELF.
   bool X86RelaxRelocations = true;
 
+  bool X86APXRelaxRelocations = false;
+
   bool X86Sse2Avx = false;
 
   std::optional<unsigned> OutputAsmVariant;
diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h 
b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
index 5e82bc53f3b5e..c03c1cd29c9f1 100644
--- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -57,6 +57,8 @@ bool getImplicitMapSyms();
 
 bool getX86RelaxRelocations();
 
+bool getX86APXRelaxRelocations();
+
 bool getX86Sse2Avx();
 
 std::string getABIName();
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4b6a87edeff87..a8205fd6ca099 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -142,6 +142,7 @@ std::string llvm::computeLTOCacheKey(
   // X86RelaxRelocations. The clang driver can also pass FunctionSections,
   // DataSections and DebuggerTuning via command line flags.
   AddUnsigned(Conf.Options.MCOptions.X86RelaxRelocations);
+  AddUnsigned(Conf.Options.MCOptions.X86APXRelaxRelocations);
   AddUnsigned(Conf.Options.FunctionSections);
   AddUnsigned(Conf.Options.DataSections);
   AddUnsigned((unsigned)Conf.Options.DebuggerTuning);
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp 
b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 2adc29172f9dd..4a68e751e90c8 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -50,6 +50,7 @@ MCOPT(bool, SaveTempLabels)
 MCOPT(bool, Crel)
 MCOPT(bool, ImplicitMapSyms)
 MCOPT(bool, X86RelaxRelocations)
+MCOPT(bool, X86APXRelaxRelocations)
 MCOPT(bool, X86Sse2Avx)
 MCOPT(std::string, ABIName)
 MCOPT(std::string, AsSecureLogFile)
@@ -150,6 +151,14 @@ 
llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
       cl::init(true));
   MCBINDOPT(X86RelaxRelocations);
 
+  static cl::opt<bool> X86APXRelaxRelocations(
+      "x86-apx-relax-relocations",
+      cl::desc("Emit APX relocation types on x86-64 ELF, including "
+               "CODE_4_GOTPCRELX/CODE_4_GOTPC32_TLSDESC/CODE_4_GOTTPOFF/"
+               "CODE_6_GOTTPOFF"),
+      cl::init(false));
+  MCBINDOPT(X86APXRelaxRelocations);
+
   static cl::opt<bool> X86Sse2Avx(
       "x86-sse2avx", cl::desc("Specify that the assembler should encode SSE "
                               "instructions with VEX prefix"));
@@ -185,6 +194,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
   Options.Crel = getCrel();
   Options.ImplicitMapSyms = getImplicitMapSyms();
   Options.X86RelaxRelocations = getX86RelaxRelocations();
+  Options.X86APXRelaxRelocations = getX86APXRelaxRelocations();
   Options.X86Sse2Avx = getX86Sse2Avx();
   Options.EmitDwarfUnwind = getEmitDwarfUnwind();
   Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical();
diff --git a/llvm/lib/Target/X86/CMakeLists.txt 
b/llvm/lib/Target/X86/CMakeLists.txt
index 9553a8619feb5..5b48b1237e783 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -89,6 +89,7 @@ set(sources
   GISel/X86InstructionSelector.cpp
   GISel/X86LegalizerInfo.cpp
   GISel/X86RegisterBankInfo.cpp
+  X86SuppressEGPRAndNDDForReloc.cpp
   )
 
 add_llvm_target(X86CodeGen ${sources}
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h 
b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 569484704a249..fb5006a4e18ab 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -17,6 +17,8 @@
 #define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86BASEINFO_H
 
 #include "X86MCTargetDesc.h"
+#include "X86RegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/MC/MCInstrDesc.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1257,6 +1259,26 @@ inline bool isX86_64ExtendedReg(MCRegister Reg) {
   return false;
 }
 
+inline const TargetRegisterClass *
+constrainRegClassToNonRex2(const TargetRegisterClass *RC) {
+  switch (RC->getID()) {
+  default:
+    return RC;
+  case X86::GR8RegClassID:
+    return &X86::GR8_NOREX2RegClass;
+  case X86::GR16RegClassID:
+    return &X86::GR16_NOREX2RegClass;
+  case X86::GR32RegClassID:
+    return &X86::GR32_NOREX2RegClass;
+  case X86::GR64RegClassID:
+    return &X86::GR64_NOREX2RegClass;
+  case X86::GR32_NOSPRegClassID:
+    return &X86::GR32_NOREX2_NOSPRegClass;
+  case X86::GR64_NOSPRegClassID:
+    return &X86::GR64_NOREX2_NOSPRegClass;
+  }
+}
+
 inline bool canUseApxExtendedReg(const MCInstrDesc &Desc) {
   uint64_t TSFlags = Desc.TSFlags;
   uint64_t Encoding = TSFlags & EncodingMask;
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp 
b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
index cac4b81429b00..e683c775627db 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -190,7 +190,8 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
   case X86MCExpr::VK_TLSCALL:
     return ELF::R_X86_64_TLSDESC_CALL;
   case X86MCExpr::VK_TLSDESC:
-    return ((unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2)
+    return ((unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2 &&
+            Ctx.getTargetOptions()->X86APXRelaxRelocations)
                ? ELF::R_X86_64_CODE_4_GOTPC32_TLSDESC
                : ELF::R_X86_64_GOTPC32_TLSDESC;
   case X86MCExpr::VK_TLSGD:
@@ -198,11 +199,13 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
     return ELF::R_X86_64_TLSGD;
   case X86MCExpr::VK_GOTTPOFF:
     checkIs32(Ctx, Loc, Type);
-    if ((unsigned)Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
-        (unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2)
-      return ELF::R_X86_64_CODE_4_GOTTPOFF;
-    else if ((unsigned)Kind == X86::reloc_riprel_4byte_relax_evex)
-      return ELF::R_X86_64_CODE_6_GOTTPOFF;
+    if (Ctx.getTargetOptions()->X86APXRelaxRelocations) {
+      if ((unsigned)Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
+          (unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2)
+        return ELF::R_X86_64_CODE_4_GOTTPOFF;
+      else if ((unsigned)Kind == X86::reloc_riprel_4byte_relax_evex)
+        return ELF::R_X86_64_CODE_6_GOTTPOFF;
+    }
     return ELF::R_X86_64_GOTTPOFF;
   case X86MCExpr::VK_TLSLD:
     checkIs32(Ctx, Loc, Type);
@@ -227,7 +230,10 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
       return ELF::R_X86_64_REX_GOTPCRELX;
     case X86::reloc_riprel_4byte_relax_rex2:
     case X86::reloc_riprel_4byte_movq_load_rex2:
-      return ELF::R_X86_64_CODE_4_GOTPCRELX;
+      if (Ctx.getTargetOptions()->X86APXRelaxRelocations)
+        return ELF::R_X86_64_CODE_4_GOTPCRELX;
+      else
+        return ELF::R_X86_64_GOTPCREL;
     }
     llvm_unreachable("unexpected relocation type!");
   case X86MCExpr::VK_GOTPCREL_NORELAX:
diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 48a3fe1934a96..3471420a51bb2 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -169,6 +169,7 @@ FunctionPass *createX86LoadValueInjectionRetHardeningPass();
 FunctionPass *createX86SpeculativeLoadHardeningPass();
 FunctionPass *createX86SpeculativeExecutionSideEffectSuppression();
 FunctionPass *createX86ArgumentStackSlotPass();
+FunctionPass *createX86SuppressEGPRAndNDDForRelocPass();
 
 void initializeCompressEVEXPassPass(PassRegistry &);
 void initializeFPSPass(PassRegistry &);
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp 
b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 459e15031ee16..2d640b9f42735 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -102,22 +102,7 @@ X86InstrInfo::getRegClass(const MCInstrDesc &MCID, 
unsigned OpNum,
   if (X86II::canUseApxExtendedReg(MCID))
     return RC;
 
-  switch (RC->getID()) {
-  default:
-    return RC;
-  case X86::GR8RegClassID:
-    return &X86::GR8_NOREX2RegClass;
-  case X86::GR16RegClassID:
-    return &X86::GR16_NOREX2RegClass;
-  case X86::GR32RegClassID:
-    return &X86::GR32_NOREX2RegClass;
-  case X86::GR64RegClassID:
-    return &X86::GR64_NOREX2RegClass;
-  case X86::GR32_NOSPRegClassID:
-    return &X86::GR32_NOREX2_NOSPRegClass;
-  case X86::GR64_NOSPRegClassID:
-    return &X86::GR64_NOREX2_NOSPRegClass;
-  }
+  return X86II::constrainRegClassToNonRex2(RC);
 }
 
 bool X86InstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
diff --git a/llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp 
b/llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp
new file mode 100644
index 0000000000000..8dfce37274dc0
--- /dev/null
+++ b/llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp
@@ -0,0 +1,145 @@
+//==- X86SuppressEGPRAndNDDForReloc.cpp - Suppress EGPR/NDD for relocations 
-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This pass is added to suppress EGPR and NDD for relocations. It's used
+/// together with disabling emitting APX relocation types for backward
+/// compatibility with old version of linker (like before LD 2.43). It can 
avoid
+/// the instructions updated incorrectly by old version of linker if the
+/// instructions are with APX EGPR/NDD features + the relocations other than 
APX
+/// ones (like GOTTPOFF).
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "X86.h"
+#include "X86RegisterInfo.h"
+#include "X86Subtarget.h"
+
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "x86-suppress-egpr-and-ndd-for-relocation"
+
+static cl::opt<bool> X86SuppressEGPRAndNDDForReloc(
+    DEBUG_TYPE,
+    cl::desc("Suppress EGPR and NDD for instructions with relocations on "
+             "x86-64 ELF"),
+    cl::init(true));
+
+namespace {
+class X86SuppressEGPRAndNDDForRelocPass : public MachineFunctionPass {
+public:
+  X86SuppressEGPRAndNDDForRelocPass() : MachineFunctionPass(ID) {}
+
+  StringRef getPassName() const override {
+    return "X86 Suppress EGPR and NDD for relocation";
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+private:
+  static char ID;
+};
+} // namespace
+
+char X86SuppressEGPRAndNDDForRelocPass::ID = 0;
+
+FunctionPass *llvm::createX86SuppressEGPRAndNDDForRelocPass() {
+  return new X86SuppressEGPRAndNDDForRelocPass();
+}
+
+static void suppressEGPRRegClass(MachineFunction &MF, MachineInstr &MI) {
+  MachineRegisterInfo *MRI = &MF.getRegInfo();
+  auto Reg = MI.getOperand(0).getReg();
+  if (!Reg.isVirtual()) {
+    assert(!X86II::isApxExtendedReg(Reg) && "APX EGPR is used unexpectedly.");
+    return;
+  }
+
+  auto *RC = MRI->getRegClass(Reg);
+  auto *NewRC = X86II::constrainRegClassToNonRex2(RC);
+  MRI->setRegClass(Reg, NewRC);
+}
+
+bool X86SuppressEGPRAndNDDForRelocPass::runOnMachineFunction(
+    MachineFunction &MF) {
+  if (MF.getTarget().Options.MCOptions.X86APXRelaxRelocations ||
+      !X86SuppressEGPRAndNDDForReloc)
+    return false;
+  const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
+  if (!ST.hasEGPR() && !ST.hasNDD() && !ST.hasNF())
+    return false;
+
+  for (MachineBasicBlock &MBB : MF) {
+    for (MachineInstr &MI : MBB) {
+      unsigned Opcode = MI.getOpcode();
+      switch (Opcode) {
+        // For GOTPC32_TLSDESC, it's emitted with physical register (EAX/RAX) 
in
+        // X86AsmPrinter::LowerTlsAddr, and there is no corresponding target
+        // flag for it, so we don't need to handle LEA64r with TLSDESC and EGPR
+        // in this pass (before emitting assembly).
+
+      case X86::ADC32rm:
+      case X86::ADD32rm:
+      case X86::AND32rm:
+      case X86::CMP32rm:
+      case X86::MOV32rm:
+      case X86::OR32rm:
+      case X86::SBB32rm:
+      case X86::SUB32rm:
+      case X86::TEST32mr:
+      case X86::XOR32rm:
+      case X86::CALL64m:
+      case X86::JMP64m:
+      case X86::TAILJMPm64:
+      case X86::TEST64mr:
+      case X86::ADC64rm:
+      case X86::ADD64rm:
+      case X86::AND64rm:
+      case X86::CMP64rm:
+      case X86::OR64rm:
+      case X86::SBB64rm:
+      case X86::SUB64rm:
+      case X86::XOR64rm: {
+        for (auto &MO : MI.operands()) {
+          if (MO.getTargetFlags() == X86II::MO_GOTTPOFF ||
+              MO.getTargetFlags() == X86II::MO_GOTPCREL)
+            suppressEGPRRegClass(MF, MI);
+        }
+        break;
+      }
+      case X86::MOV64rm: {
+        if (MI.getOperand(4).getTargetFlags() == X86II::MO_GOTTPOFF)
+          suppressEGPRRegClass(MF, MI);
+        break;
+      }
+      case X86::ADD64rm_NF:
+      case X86::ADD64rm_ND:
+      case X86::ADD64mr_ND:
+      case X86::ADD64mr_NF_ND:
+      case X86::ADD64rm_NF_ND: {
+        // TODO: implement this if there is a case of NDD/NF instructions with
+        // GOTTPOFF relocation (update the instructions to ADD64rm/ADD64mr and
+        // suppress EGPR)
+        for (auto &MO : MI.operands())
+          assert((MO.getTargetFlags() != X86II::MO_GOTTPOFF) &&
+                 "Suppressing NDD/NF instructions with relocation is "
+                 "unimplemented!");
+        break;
+      }
+      }
+    }
+  }
+
+  return true;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp 
b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 4cecbbf27aa30..ee54c76355cf3 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -567,6 +567,8 @@ void X86PassConfig::addPreRegAlloc() {
     addPass(createX86PreTileConfigPass());
   else
     addPass(createX86FastPreTileConfigPass());
+
+  addPass(createX86SuppressEGPRAndNDDForRelocPass());
 }
 
 void X86PassConfig::addMachineSSAOptimization() {
diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll 
b/llvm/test/CodeGen/X86/O0-pipeline.ll
index 6d824f8b510af..9747be1a891be 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -45,6 +45,7 @@
 ; CHECK-NEXT:       X86 EFLAGS copy lowering
 ; CHECK-NEXT:       X86 DynAlloca Expander
 ; CHECK-NEXT:       Fast Tile Register Preconfigure
+; CHECK-NEXT:       X86 Suppress EGPR and NDD for relocation
 ; CHECK-NEXT:       Eliminate PHI nodes for register allocation
 ; CHECK-NEXT:       Two-Address instruction pass
 ; CHECK-NEXT:       Fast Register Allocator
diff --git a/llvm/test/CodeGen/X86/apx/tls-desc.ll 
b/llvm/test/CodeGen/X86/apx/tls-desc.ll
new file mode 100644
index 0000000000000..244e524795a44
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/tls-desc.ll
@@ -0,0 +1,96 @@
+; RUN: llc -mattr=+egpr %s -mtriple=x86_64 --relocation-model=pic 
-enable-tlsdesc -filetype=obj -x86-apx-relax-relocations=true -o %t.o
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.o | FileCheck %s 
--check-prefix=TLSDESC_APXRELAX
+; RUN: echo '.tbss; .globl b,c,d,e,f,g,h,i,j; b: .zero 4;c: .zero 4;d: .zero 
4;e: .zero 4;f: .zero 4;g: .zero 4;h: .zero 4;i: .zero 4;j: .zero 4' | llvm-mc 
-filetype=obj -triple=x86_64 - -o %t1.o
+
+; RUN: llc -mattr=+egpr %s -mtriple=x86_64 --relocation-model=pic 
-enable-tlsdesc -filetype=obj -o %t.o
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.o | FileCheck %s 
--check-prefix=TLSDESC_NOAPXRELAX
+; RUN: echo '.tbss; .globl b,c,d,e,f,g,h,i,j; b: .zero 4;c: .zero 4;d: .zero 
4;e: .zero 4;f: .zero 4;g: .zero 4;h: .zero 4;i: .zero 4;j: .zero 4' | llvm-mc 
-filetype=obj -triple=x86_64 - -o %t1.o
+
+; RUN: llc -mattr=+egpr %s -mtriple=x86_64 -filetype=obj -o %t.o 
-x86-apx-relax-relocations=true
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.o | FileCheck %s 
--check-prefix=GOTTPOFF_APXRELAX
+; RUN: echo '.tbss; .globl b,c,d,e,f,g,h,i,j; b: .zero 4;c: .zero 4;d: .zero 
4;e: .zero 4;f: .zero 4;g: .zero 4;h: .zero 4;i: .zero 4;j: .zero 4' | llvm-mc 
-filetype=obj -triple=x86_64 - -o %t1.o
+; RUN: ld.lld  %t.o %t1.o -o %t.so
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.so | FileCheck %s 
--check-prefix=GOTTPOFF_LD_APXRELAX
+
+; RUN: llc -mattr=+egpr %s -mtriple=x86_64 -filetype=obj -o %t.o
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.o | FileCheck %s 
--check-prefix=GOTTPOFF_NOAPXRELAX
+; RUN: echo '.tbss; .globl b,c,d,e,f,g,h,i,j; b: .zero 4;c: .zero 4;d: .zero 
4;e: .zero 4;f: .zero 4;g: .zero 4;h: .zero 4;i: .zero 4;j: .zero 4' | llvm-mc 
-filetype=obj -triple=x86_64 - -o %t1.o
+; RUN: ld.lld  %t.o %t1.o -o %t.so
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.so | FileCheck %s 
--check-prefix=GOTTPOFF_LD_NOAPXRELAX
+
+; RUN: llc -mattr=+egpr %s -mtriple=x86_64 -filetype=obj -o %t.o 
-x86-suppress-egpr-and-ndd-for-relocation=false
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.o | FileCheck %s 
--check-prefix=GOTTPOFF_NOAPXRELAX_APXINSTR
+; RUN: echo '.tbss; .globl b,c,d,e,f,g,h,i,j; b: .zero 4;c: .zero 4;d: .zero 
4;e: .zero 4;f: .zero 4;g: .zero 4;h: .zero 4;i: .zero 4;j: .zero 4' | llvm-mc 
-filetype=obj -triple=x86_64 - -o %t1.o
+; RUN: ld.lld  %t.o %t1.o -o %t.so
+; RUN: llvm-objdump --no-print-imm-hex -dr %t.so | FileCheck %s 
--check-prefix=GOTTPOFF_LD_NOAPXRELAX_APXINSTR
+
+; TLSDESC_APXRELAX: d5 18 89 c0       movq %rax, %r16
+; TLSDESC_APXRELAX-NEXT: 48 8d 05 00 00 00 00       leaq (%rip), %rax
+; TLSDESC_APXRELAX-NEXT: R_X86_64_GOTPC32_TLSDESC j-0x4
+; TLSDESC_NOAPXRELAX: d5 18 89 c0       movq %rax, %r16
+; TLSDESC_NOAPXRELAX-NEXT: 48 8d 05 00 00 00 00       leaq (%rip), %rax
+; TLSDESC_NOAPXRELAX-NEXT: R_X86_64_GOTPC32_TLSDESC j-0x4
+
+; GOTTPOFF_APXRELAX: d5 48 8b 05 00 00 00 00       movq (%rip), %r16
+; GOTTPOFF_APXRELAX-NEXT: R_X86_64_CODE_4_GOTTPOFF j-0x4
+
+; GOTTPOFF_NOAPXRELAX: 48 8b 1d 00 00 00 00       movq (%rip), %rbx
+; GOTTPOFF_NOAPXRELAX-NEXT: R_X86_64_GOTTPOFF j-0x4
+
+; GOTTPOFF_LD_APXRELAX: d5 18 c7 c0 fc ff ff ff       movq $-4, %r16
+; GOTTPOFF_LD_NOAPXRELAX: 48 c7 c3 fc ff ff ff       movq $-4, %rbx
+
+; GOTTPOFF_NOAPXRELAX_APXINSTR: d5 48 8b 05 00 00 00 00       movq (%rip), %r16
+; GOTTPOFF_NOAPXRELAX_APXINSTR-NEXT: R_X86_64_GOTTPOFF j-0x4
+
+; The instruction is incorrectly updated by the LLD linker, if it's emitted 
with
+; EGPR and R_X86_64_GOTTPOFF relocation.
+; GOTTPOFF_LD_NOAPXRELAX_APXINSTR: d5 48 c7 c0 fc ff ff ff       movq $-4, %rax
+
+@a = thread_local global i32 0, align 4
+@b = external thread_local global i32, align 4
+@c = external thread_local global i32, align 4
+@d = external thread_local global i32, align 4
+@e = external thread_local global i32, align 4
+@f = external thread_local global i32, align 4
+@g = external thread_local global i32, align 4
+@h = external thread_local global i32, align 4
+@i = external thread_local global i32, align 4
+@j = external thread_local global i32, align 4
+
+define i32 @f2() nounwind {
+  %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @a)
+  %2 = tail call ptr @llvm.threadlocal.address.p0(ptr @b)
+  %3 = tail call ptr @llvm.threadlocal.address.p0(ptr @c)
+  %4 = tail call ptr @llvm.threadlocal.address.p0(ptr @d)
+  %5 = tail call ptr @llvm.threadlocal.address.p0(ptr @e)
+  %6 = tail call ptr @llvm.threadlocal.address.p0(ptr @f)
+  %7 = tail call ptr @llvm.threadlocal.address.p0(ptr @g)
+  %8 = tail call ptr @llvm.threadlocal.address.p0(ptr @h)
+  %9 = tail call ptr @llvm.threadlocal.address.p0(ptr @i)
+  %10 = tail call ptr @llvm.threadlocal.address.p0(ptr @j)
+
+  %11 = load i32, ptr %1
+  %12 = load i32, ptr %2
+  %13 = load i32, ptr %3
+  %14 = load i32, ptr %4
+  %15 = load i32, ptr %5
+  %16 = load i32, ptr %6
+  %17 = load i32, ptr %7
+  %18 = load i32, ptr %8
+  %19 = load i32, ptr %9
+  %20 = load i32, ptr %10
+
+  %21 = add i32 %11, %12
+  %22 = add i32 %13, %14
+  %23 = add i32 %15, %16
+  %24 = add i32 %17, %18
+  %25 = add i32 %19, %20
+
+  %26 = add i32 %21, %22
+  %27 = add i32 %23, %24
+  %28 = add i32 %26, %27
+  %29 = add i32 %25, %28
+
+  ret i32 %29
+}
diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll 
b/llvm/test/CodeGen/X86/opt-pipeline.ll
index d72f517cfb603..f7b3026c6dd45 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -133,11 +133,14 @@
 ; CHECK-NEXT:       MachineDominator Tree Construction
 ; CHECK-NEXT:       Machine Natural Loop Construction
 ; CHECK-NEXT:       Tile Register Pre-configure
+; CHECK-NEXT:       X86 Suppress EGPR and NDD for relocation
 ; CHECK-NEXT:       Detect Dead Lanes
 ; CHECK-NEXT:       Init Undef Pass
 ; CHECK-NEXT:       Process Implicit Definitions
 ; CHECK-NEXT:       Remove unreachable machine basic blocks
 ; CHECK-NEXT:       Live Variable Analysis
+; CHECK-NEXT:       MachineDominator Tree Construction
+; CHECK-NEXT:       Machine Natural Loop Construction
 ; CHECK-NEXT:       Eliminate PHI nodes for register allocation
 ; CHECK-NEXT:       Two-Address instruction pass
 ; CHECK-NEXT:       Slot index numbering
diff --git a/llvm/test/MC/ELF/relocation-alias.s 
b/llvm/test/MC/ELF/relocation-alias.s
index 7701f1107e5a6..0f68dc3b755c6 100644
--- a/llvm/test/MC/ELF/relocation-alias.s
+++ b/llvm/test/MC/ELF/relocation-alias.s
@@ -1,7 +1,11 @@
-# RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t
+# RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t 
-x86-apx-relax-relocations=true
 # RUN: llvm-objdump --no-print-imm-hex -dr %t | FileCheck %s
 # RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYM
 
+# RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t
+# RUN: llvm-objdump --no-print-imm-hex -dr %t | FileCheck %s 
--check-prefix=NOAPXREL
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYM
+
 # RUN: not llvm-mc -filetype=obj -triple x86_64 --defsym ERR=1 %s 2>&1 | 
FileCheck %s --check-prefix=ERR
 
 ## If a fixup symbol is equated to an undefined symbol, convert the fixup
@@ -18,6 +22,8 @@ movabsq $memcpy+2, %rax
 # CHECK-NEXT:   R_X86_64_REX_GOTPCRELX  abs-0x4
 # CHECK:      movq (%rip), %r16
 # CHECK-NEXT:   R_X86_64_CODE_4_GOTPCRELX abs-0x4
+# NOAPXREL:      movq (%rip), %r16
+# NOAPXREL-NEXT:   R_X86_64_GOTPCREL abs-0x4
 movq abs@GOTPCREL(%rip), %rax
 movq abs@GOTPCREL(%rip), %r16
 abs = 42
diff --git a/llvm/test/MC/X86/elf-reloc-tls.s b/llvm/test/MC/X86/elf-reloc-tls.s
index 2090435859312..66d556d725dba 100644
--- a/llvm/test/MC/X86/elf-reloc-tls.s
+++ b/llvm/test/MC/X86/elf-reloc-tls.s
@@ -1,6 +1,9 @@
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t 
-x86-apx-relax-relocations=true
 # RUN: llvm-readobj -r %t | FileCheck %s
 
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s --check-prefixes=NOAPXREL
+
 # CHECK:      .rela.GOTTPOFF {
 # CHECK-NEXT:   0x3 R_X86_64_GOTTPOFF tls 0xFFFFFFFFFFFFFFFC
 # CHECK-NEXT:   0xB R_X86_64_CODE_4_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
@@ -12,6 +15,17 @@
 # CHECK-NEXT:   0x45 R_X86_64_CODE_6_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
 # CHECK-NEXT: }
 
+# NOAPXREL:      .rela.GOTTPOFF {
+# NOAPXREL-NEXT:   0x3 R_X86_64_GOTTPOFF tls 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0xB R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0x13 R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0x1D R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0x27 R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0x31 R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0x3B R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT:   0x45 R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
+# NOAPXREL-NEXT: }
+
 .section .TPOFF,"ax"
 leaq   foo@TPOFF(%rax), %rax    # R_X86_64_TPOFF32
 movabsq        $baz@TPOFF, %rax
diff --git a/llvm/test/MC/X86/gotpcrelx.s b/llvm/test/MC/X86/gotpcrelx.s
index e88c514b22690..9a8758a3550c5 100644
--- a/llvm/test/MC/X86/gotpcrelx.s
+++ b/llvm/test/MC/X86/gotpcrelx.s
@@ -1,7 +1,9 @@
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o 
-x86-apx-relax-relocations=true
 # RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefixes=CHECK,COMMON
 # RUN: llvm-mc -filetype=obj -triple=x86_64 -x86-relax-relocations=false %s -o 
%t1.o
 # RUN: llvm-readobj -r %t1.o | FileCheck %s --check-prefixes=NORELAX,COMMON
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: llvm-readobj -r %t1.o | FileCheck %s --check-prefixes=NOAPXRELAX,COMMON
 
 # COMMON:     Relocations [
 # COMMON-NEXT:  Section ({{.*}}) .rela.text {
@@ -93,6 +95,51 @@
 # NORELAX-NEXT:     R_X86_64_GOTPCREL xor
 # NORELAX-NEXT:   }
 
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX mov
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX test
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX adc
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX add
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX and
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX cmp
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX or
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX sbb
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX sub
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX xor
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX call
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCRELX jmp
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX mov
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX test
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX adc
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX add
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX and
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX cmp
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX or
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX sbb
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX sub
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX xor
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX mov
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX test
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX adc
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX add
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX and
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX cmp
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX or
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX sbb
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX sub
+# NOAPXRELAX-NEXT:     R_X86_64_REX_GOTPCRELX xor
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL mov
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL test
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL adc
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL add
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL and
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL cmp
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL or
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL sbb
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL sub
+# NOAPXRELAX-NEXT:     R_X86_64_GOTPCREL xor
+# NOAPXRELAX-NEXT:   }
+
+
 movl mov@GOTPCREL(%rip), %eax
 test %eax, test@GOTPCREL(%rip)
 adc adc@GOTPCREL(%rip), %eax
diff --git a/llvm/test/MC/X86/tlsdesc-64.s b/llvm/test/MC/X86/tlsdesc-64.s
index d1d3381751090..dd96b2409bf95 100644
--- a/llvm/test/MC/X86/tlsdesc-64.s
+++ b/llvm/test/MC/X86/tlsdesc-64.s
@@ -1,9 +1,12 @@
 # RUN: llvm-mc -triple x86_64-pc-linux-musl %s | FileCheck 
--check-prefix=PRINT %s
 
-# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-musl %s -o %t
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-musl %s -o %t 
-x86-apx-relax-relocations=true
 # RUN: llvm-readelf -s %t | FileCheck --check-prefix=SYM %s
 # RUN: llvm-objdump -d -r --no-show-raw-insn %t | FileCheck --match-full-lines 
%s
 
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-musl %s -o %t
+# RUN: llvm-objdump -d -r --no-show-raw-insn %t | FileCheck --match-full-lines 
%s --check-prefixes=NOAPXRELAX
+
 # PRINT:      leaq a@tlsdesc(%rip), %rax
 # PRINT-NEXT: callq *a@tlscall(%rax)
 
@@ -26,6 +29,9 @@ addq %fs:0, %rax
 # CHECK-NEXT: 1a: callq *(%r16)
 # CHECK-NEXT:   000000000000001a: R_X86_64_TLSDESC_CALL a
 
+# NOAPXRELAX:      12: leaq (%rip), %r16  # 0x1a <{{.*}}>
+# NOAPXRELAX-NEXT:   0000000000000016: R_X86_64_GOTPC32_TLSDESC a-0x4
+
 leaq a@tlsdesc(%rip), %r16
 call *a@tlscall(%r16)
 addq %fs:0, %r16
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index ae965e6f486aa..b4dc2fb0c3592 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -885,6 +885,8 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback 
OnIndexWrite,
   // FIXME: Check the gold version or add a new option to enable them.
   Conf.Options.MCOptions.X86RelaxRelocations = false;
 
+  Conf.Options.MCOptions.X86APXRelaxRelocations = false;
+
   // Toggle function/data sections.
   if (!codegen::getExplicitFunctionSections())
     Conf.Options.FunctionSections = SplitSections;

>From 6a6ade0a55bfdb4b53f37f08c5d29e466faaf8bd Mon Sep 17 00:00:00 2001
From: Feng Zou <feng....@intel.com>
Date: Tue, 22 Apr 2025 22:57:55 +0800
Subject: [PATCH 2/2] Fix default value for -mapx-relax-relocations option.

Rename the pass of suppressing APX features for relocation.
---
 clang/include/clang/Basic/CodeGenOptions.def  |  2 +-
 clang/include/clang/Driver/Options.td         |  2 +-
 llvm/lib/Target/X86/CMakeLists.txt            |  2 +-
 llvm/lib/Target/X86/X86.h                     |  3 +-
 ...orReloc.cpp => X86SuppressAPXForReloc.cpp} | 88 ++++++++++++-------
 llvm/lib/Target/X86/X86TargetMachine.cpp      |  3 +-
 llvm/test/CodeGen/X86/O0-pipeline.ll          |  2 +-
 .../CodeGen/X86/apx/{tls-desc.ll => tls.ll}   |  2 +-
 llvm/test/CodeGen/X86/opt-pipeline.ll         |  2 +-
 9 files changed, 68 insertions(+), 38 deletions(-)
 rename llvm/lib/Target/X86/{X86SuppressEGPRAndNDDForReloc.cpp => 
X86SuppressAPXForReloc.cpp} (56%)
 rename llvm/test/CodeGen/X86/apx/{tls-desc.ll => tls.ll} (99%)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index 875facd6cfc63..6826df2974738 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -201,7 +201,7 @@ CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal 
Linkage symbols get u
 CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using 
profile information.
 CODEGENOPT(PPCUseFullRegisterNames, 1, 0) ///< Print full register names in 
assembly
 CODEGENOPT(X86RelaxRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no}
-CODEGENOPT(X86APXRelaxRelocations, 1, 0) ///< -Wa,-mrelax-relocations={yes,no}
+CODEGENOPT(X86APXRelaxRelocations, 1, 0) ///< 
-Wa,-mapx-relax-relocations={yes,no}
 CODEGENOPT(X86Sse2Avx        , 1, 0)   ///< -Wa,-msse2avx
 
 /// When false, this attempts to generate code as if the result of an
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index a3becf76a7671..0cab7288e08d4 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -7444,7 +7444,7 @@ def mrelax_relocations_no : Flag<["-"], 
"mrelax-relocations=no">,
     MarshallingInfoNegativeFlag<CodeGenOpts<"X86RelaxRelocations">>;
 def mapx_relax_relocations_yes : Flag<["-"], "mapx-relax-relocations=yes">,
     HelpText<"Enable x86 APX relax relocations">,
-    MarshallingInfoNegativeFlag<CodeGenOpts<"X86APXRelaxRelocations">>;
+    MarshallingInfoFlag<CodeGenOpts<"X86APXRelaxRelocations">>;
 def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
   HelpText<"Save temporary labels in the symbol table. "
            "Note this may change .s semantics and shouldn't generally be used "
diff --git a/llvm/lib/Target/X86/CMakeLists.txt 
b/llvm/lib/Target/X86/CMakeLists.txt
index 5b48b1237e783..b0342ca7a3939 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -89,7 +89,7 @@ set(sources
   GISel/X86InstructionSelector.cpp
   GISel/X86LegalizerInfo.cpp
   GISel/X86RegisterBankInfo.cpp
-  X86SuppressEGPRAndNDDForReloc.cpp
+  X86SuppressAPXForReloc.cpp
   )
 
 add_llvm_target(X86CodeGen ${sources}
diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 3471420a51bb2..e6c0612101bc7 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -169,7 +169,7 @@ FunctionPass *createX86LoadValueInjectionRetHardeningPass();
 FunctionPass *createX86SpeculativeLoadHardeningPass();
 FunctionPass *createX86SpeculativeExecutionSideEffectSuppression();
 FunctionPass *createX86ArgumentStackSlotPass();
-FunctionPass *createX86SuppressEGPRAndNDDForRelocPass();
+FunctionPass *createX86SuppressAPXForRelocationPass();
 
 void initializeCompressEVEXPassPass(PassRegistry &);
 void initializeFPSPass(PassRegistry &);
@@ -205,6 +205,7 @@ void initializeX86ReturnThunksPass(PassRegistry &);
 void initializeX86SpeculativeExecutionSideEffectSuppressionPass(PassRegistry 
&);
 void initializeX86SpeculativeLoadHardeningPassPass(PassRegistry &);
 void initializeX86TileConfigPass(PassRegistry &);
+void initializeX86SuppressAPXForRelocationPassPass(PassRegistry &);
 
 namespace X86AS {
 enum : unsigned {
diff --git a/llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp 
b/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
similarity index 56%
rename from llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp
rename to llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
index 8dfce37274dc0..0e9c0e044eb7f 100644
--- a/llvm/lib/Target/X86/X86SuppressEGPRAndNDDForReloc.cpp
+++ b/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
@@ -1,4 +1,4 @@
-//==- X86SuppressEGPRAndNDDForReloc.cpp - Suppress EGPR/NDD for relocations 
-=//
+//===- X86SuppressAPXForReloc.cpp - Suppress APX features for relocations 
-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,12 +7,12 @@
 
//===----------------------------------------------------------------------===//
 /// \file
 ///
-/// This pass is added to suppress EGPR and NDD for relocations. It's used
+/// This pass is added to suppress APX features for relocations. It's used
 /// together with disabling emitting APX relocation types for backward
 /// compatibility with old version of linker (like before LD 2.43). It can 
avoid
 /// the instructions updated incorrectly by old version of linker if the
-/// instructions are with APX EGPR/NDD features + the relocations other than 
APX
-/// ones (like GOTTPOFF).
+/// instructions are with APX EGPR/NDD/NF features + the relocations other than
+/// APX ones (like GOTTPOFF).
 ///
 
//===----------------------------------------------------------------------===//
 
@@ -23,44 +23,52 @@
 #include "X86Subtarget.h"
 
 #include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/InitializePasses.h"
 #include "llvm/Target/TargetMachine.h"
 
 using namespace llvm;
 
-#define DEBUG_TYPE "x86-suppress-egpr-and-ndd-for-relocation"
+#define DEBUG_TYPE "x86-suppress-apx-for-relocation"
 
-static cl::opt<bool> X86SuppressEGPRAndNDDForReloc(
+static cl::opt<bool> X86SuppressAPXForReloc(
     DEBUG_TYPE,
-    cl::desc("Suppress EGPR and NDD for instructions with relocations on "
-             "x86-64 ELF"),
+    cl::desc("Suppress APX features (EGPR, NDD and NF) for instructions with "
+             "relocations on x86-64 ELF"),
     cl::init(true));
 
 namespace {
-class X86SuppressEGPRAndNDDForRelocPass : public MachineFunctionPass {
+class X86SuppressAPXForRelocationPass : public MachineFunctionPass {
 public:
-  X86SuppressEGPRAndNDDForRelocPass() : MachineFunctionPass(ID) {}
+  X86SuppressAPXForRelocationPass() : MachineFunctionPass(ID) {}
 
   StringRef getPassName() const override {
-    return "X86 Suppress EGPR and NDD for relocation";
+    return "X86 Suppress APX features for relocation";
   }
 
   bool runOnMachineFunction(MachineFunction &MF) override;
 
-private:
   static char ID;
 };
 } // namespace
 
-char X86SuppressEGPRAndNDDForRelocPass::ID = 0;
+char X86SuppressAPXForRelocationPass::ID = 0;
 
-FunctionPass *llvm::createX86SuppressEGPRAndNDDForRelocPass() {
-  return new X86SuppressEGPRAndNDDForRelocPass();
+INITIALIZE_PASS_BEGIN(X86SuppressAPXForRelocationPass, DEBUG_TYPE,
+                      "X86 Suppress APX features for relocation", false, false)
+INITIALIZE_PASS_END(X86SuppressAPXForRelocationPass, DEBUG_TYPE,
+                    "X86 Suppress APX features for relocation", false, false)
+
+FunctionPass *llvm::createX86SuppressAPXForRelocationPass() {
+  return new X86SuppressAPXForRelocationPass();
 }
 
-static void suppressEGPRRegClass(MachineFunction &MF, MachineInstr &MI) {
+static void suppressEGPRRegClass(MachineFunction &MF, MachineInstr &MI,
+                                 unsigned int OpNum) {
   MachineRegisterInfo *MRI = &MF.getRegInfo();
-  auto Reg = MI.getOperand(0).getReg();
+  auto Reg = MI.getOperand(OpNum).getReg();
   if (!Reg.isVirtual()) {
     assert(!X86II::isApxExtendedReg(Reg) && "APX EGPR is used unexpectedly.");
     return;
@@ -71,10 +79,10 @@ static void suppressEGPRRegClass(MachineFunction &MF, 
MachineInstr &MI) {
   MRI->setRegClass(Reg, NewRC);
 }
 
-bool X86SuppressEGPRAndNDDForRelocPass::runOnMachineFunction(
+bool X86SuppressAPXForRelocationPass::runOnMachineFunction(
     MachineFunction &MF) {
   if (MF.getTarget().Options.MCOptions.X86APXRelaxRelocations ||
-      !X86SuppressEGPRAndNDDForReloc)
+      !X86SuppressAPXForReloc)
     return false;
   const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
   if (!ST.hasEGPR() && !ST.hasNDD() && !ST.hasNF())
@@ -113,28 +121,48 @@ bool 
X86SuppressEGPRAndNDDForRelocPass::runOnMachineFunction(
       case X86::XOR64rm: {
         for (auto &MO : MI.operands()) {
           if (MO.getTargetFlags() == X86II::MO_GOTTPOFF ||
-              MO.getTargetFlags() == X86II::MO_GOTPCREL)
-            suppressEGPRRegClass(MF, MI);
+              MO.getTargetFlags() == X86II::MO_GOTPCREL) {
+            suppressEGPRRegClass(MF, MI, 0);
+            break;
+          }
         }
         break;
       }
       case X86::MOV64rm: {
-        if (MI.getOperand(4).getTargetFlags() == X86II::MO_GOTTPOFF)
-          suppressEGPRRegClass(MF, MI);
+        for (auto &MO : MI.operands()) {
+          if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
+            suppressEGPRRegClass(MF, MI, 0);
+            break;
+          }
+        }
         break;
       }
       case X86::ADD64rm_NF:
       case X86::ADD64rm_ND:
-      case X86::ADD64mr_ND:
-      case X86::ADD64mr_NF_ND:
       case X86::ADD64rm_NF_ND: {
-        // TODO: implement this if there is a case of NDD/NF instructions with
-        // GOTTPOFF relocation (update the instructions to ADD64rm/ADD64mr and
-        // suppress EGPR)
-        for (auto &MO : MI.operands())
+        for (auto &MO : MI.operands()) {
+          if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
+            suppressEGPRRegClass(MF, MI, 0);
+            const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(X86::ADD64rm);
+            MI.setDesc(NewDesc);
+            if (Opcode == X86::ADD64rm_ND || Opcode == X86::ADD64rm_NF_ND) {
+              MI.tieOperands(0, 1);
+              MI.getOperand(1).setIsKill(false);
+              suppressEGPRRegClass(MF, MI, 1);
+            }
+            break;
+          }
+        }
+        break;
+      }
+      case X86::ADD64mr_ND:
+      case X86::ADD64mr_NF_ND: {
+        for ([[maybe_unused]] auto &MO : MI.operands()) {
           assert((MO.getTargetFlags() != X86II::MO_GOTTPOFF) &&
-                 "Suppressing NDD/NF instructions with relocation is "
+                 "Suppressing this instruction with relocation is "
                  "unimplemented!");
+          break;
+        }
         break;
       }
       }
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp 
b/llvm/lib/Target/X86/X86TargetMachine.cpp
index ee54c76355cf3..4a333b407e0e0 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -105,6 +105,7 @@ extern "C" LLVM_C_ABI void LLVMInitializeX86Target() {
   initializeX86FixupInstTuningPassPass(PR);
   initializeX86FixupVectorConstantsPassPass(PR);
   initializeX86DynAllocaExpanderPass(PR);
+  initializeX86SuppressAPXForRelocationPassPass(PR);
 }
 
 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
@@ -568,7 +569,7 @@ void X86PassConfig::addPreRegAlloc() {
   else
     addPass(createX86FastPreTileConfigPass());
 
-  addPass(createX86SuppressEGPRAndNDDForRelocPass());
+  addPass(createX86SuppressAPXForRelocationPass());
 }
 
 void X86PassConfig::addMachineSSAOptimization() {
diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll 
b/llvm/test/CodeGen/X86/O0-pipeline.ll
index 9747be1a891be..fedd57d99bbcf 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -45,7 +45,7 @@
 ; CHECK-NEXT:       X86 EFLAGS copy lowering
 ; CHECK-NEXT:       X86 DynAlloca Expander
 ; CHECK-NEXT:       Fast Tile Register Preconfigure
-; CHECK-NEXT:       X86 Suppress EGPR and NDD for relocation
+; CHECK-NEXT:       X86 Suppress APX features for relocation
 ; CHECK-NEXT:       Eliminate PHI nodes for register allocation
 ; CHECK-NEXT:       Two-Address instruction pass
 ; CHECK-NEXT:       Fast Register Allocator
diff --git a/llvm/test/CodeGen/X86/apx/tls-desc.ll 
b/llvm/test/CodeGen/X86/apx/tls.ll
similarity index 99%
rename from llvm/test/CodeGen/X86/apx/tls-desc.ll
rename to llvm/test/CodeGen/X86/apx/tls.ll
index 244e524795a44..e11f0fdc35081 100644
--- a/llvm/test/CodeGen/X86/apx/tls-desc.ll
+++ b/llvm/test/CodeGen/X86/apx/tls.ll
@@ -18,7 +18,7 @@
 ; RUN: ld.lld  %t.o %t1.o -o %t.so
 ; RUN: llvm-objdump --no-print-imm-hex -dr %t.so | FileCheck %s 
--check-prefix=GOTTPOFF_LD_NOAPXRELAX
 
-; RUN: llc -mattr=+egpr %s -mtriple=x86_64 -filetype=obj -o %t.o 
-x86-suppress-egpr-and-ndd-for-relocation=false
+; RUN: llc -mattr=+egpr %s -mtriple=x86_64 -filetype=obj -o %t.o 
-x86-suppress-apx-for-relocation=false
 ; RUN: llvm-objdump --no-print-imm-hex -dr %t.o | FileCheck %s 
--check-prefix=GOTTPOFF_NOAPXRELAX_APXINSTR
 ; RUN: echo '.tbss; .globl b,c,d,e,f,g,h,i,j; b: .zero 4;c: .zero 4;d: .zero 
4;e: .zero 4;f: .zero 4;g: .zero 4;h: .zero 4;i: .zero 4;j: .zero 4' | llvm-mc 
-filetype=obj -triple=x86_64 - -o %t1.o
 ; RUN: ld.lld  %t.o %t1.o -o %t.so
diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll 
b/llvm/test/CodeGen/X86/opt-pipeline.ll
index f7b3026c6dd45..1b76c852c2468 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -133,7 +133,7 @@
 ; CHECK-NEXT:       MachineDominator Tree Construction
 ; CHECK-NEXT:       Machine Natural Loop Construction
 ; CHECK-NEXT:       Tile Register Pre-configure
-; CHECK-NEXT:       X86 Suppress EGPR and NDD for relocation
+; CHECK-NEXT:       X86 Suppress APX features for relocation
 ; CHECK-NEXT:       Detect Dead Lanes
 ; CHECK-NEXT:       Init Undef Pass
 ; CHECK-NEXT:       Process Implicit Definitions

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to