[llvm] bd6addc - [X86][APX] Suppress EGPR/NDD instructions for relocations (#136660)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 29 04:13:03 PDT 2025


Author: Feng Zou
Date: 2025-04-29T19:12:59+08:00
New Revision: bd6addc032b1ea764494e2de135b5b2c46ee6aca

URL: https://github.com/llvm/llvm-project/commit/bd6addc032b1ea764494e2de135b5b2c46ee6aca
DIFF: https://github.com/llvm/llvm-project/commit/bd6addc032b1ea764494e2de135b5b2c46ee6aca.diff

LOG: [X86][APX] Suppress EGPR/NDD instructions for relocations (#136660)

Suppress EGPR/NDD instructions for relocations to avoid APX relocation
types emitted. This is to keep backward compatibility with old version
of linkers without APX support. The use case is to try APX features with
LLVM + old built-in linker on RHEL9 OS which is expected to be EOL in
2032.
If there are APX relocation types, the old version of linkers would
raise "unsupported relocation type" error. Example:
```
$ llvm-mc -filetype=obj -o got.o -triple=x86_64-unknown-linux got.s
$ ld got.o -o got.exe
ld: got.o: unsupported relocation type 0x2b
...

$ cat got.s
...
movq foo at GOTPCREL(%rip), %r16

$ llvm-objdump -dr got.o
...
1: d5 48 8b 05 00 00 00 00       movq    (%rip), %r16
0000000000000005:  R_X86_64_CODE_4_GOTPCRELX    foo-0x4
```

Added: 
    llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
    llvm/test/CodeGen/X86/apx/reloc.mir
    llvm/test/CodeGen/X86/apx/tls.ll

Modified: 
    llvm/lib/Target/X86/CMakeLists.txt
    llvm/lib/Target/X86/X86.h
    llvm/lib/Target/X86/X86CompressEVEX.cpp
    llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
    llvm/lib/Target/X86/X86InstrInfo.cpp
    llvm/lib/Target/X86/X86InstrInfo.h
    llvm/lib/Target/X86/X86RegisterInfo.cpp
    llvm/lib/Target/X86/X86RegisterInfo.h
    llvm/lib/Target/X86/X86TargetMachine.cpp
    llvm/test/CodeGen/X86/O0-pipeline.ll
    llvm/test/CodeGen/X86/apx/add.ll
    llvm/test/CodeGen/X86/apx/and.ll
    llvm/test/CodeGen/X86/apx/compress-evex.mir
    llvm/test/CodeGen/X86/apx/dec.ll
    llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
    llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
    llvm/test/CodeGen/X86/apx/imul.ll
    llvm/test/CodeGen/X86/apx/inc.ll
    llvm/test/CodeGen/X86/apx/neg.ll
    llvm/test/CodeGen/X86/apx/or.ll
    llvm/test/CodeGen/X86/apx/shl.ll
    llvm/test/CodeGen/X86/apx/shr.ll
    llvm/test/CodeGen/X86/apx/sub.ll
    llvm/test/CodeGen/X86/apx/xor.ll
    llvm/test/CodeGen/X86/opt-pipeline.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt
index 9553a8619feb5..701140fc4a9dc 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -78,6 +78,7 @@ set(sources
   X86SpeculativeLoadHardening.cpp
   X86SpeculativeExecutionSideEffectSuppression.cpp
   X86Subtarget.cpp
+  X86SuppressAPXForReloc.cpp
   X86TargetMachine.cpp
   X86TargetObjectFile.cpp
   X86TargetTransformInfo.cpp

diff  --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 48a3fe1934a96..e6c0612101bc7 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 *createX86SuppressAPXForRelocationPass();
 
 void initializeCompressEVEXPassPass(PassRegistry &);
 void initializeFPSPass(PassRegistry &);
@@ -204,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/X86CompressEVEX.cpp b/llvm/lib/Target/X86/X86CompressEVEX.cpp
index 7883f720ffa79..84f63f312a764 100644
--- a/llvm/lib/Target/X86/X86CompressEVEX.cpp
+++ b/llvm/lib/Target/X86/X86CompressEVEX.cpp
@@ -58,6 +58,8 @@ using namespace llvm;
 
 #define DEBUG_TYPE COMP_EVEX_NAME
 
+extern cl::opt<bool> X86EnableAPXForRelocation;
+
 namespace {
 // Including the generated EVEX compression tables.
 #define GET_X86_COMPRESS_EVEX_TABLE
@@ -252,6 +254,13 @@ static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
       if (MI.definesRegister(Super, /*TRI=*/nullptr))
         IsRedundantNDD = false;
     }
+
+    // ADDrm/mr instructions with NDD + relocation had been transformed to the
+    // instructions without NDD in X86SuppressAPXForRelocation pass. That is to
+    // keep backward compatibility with linkers without APX support.
+    if (!X86EnableAPXForRelocation)
+      assert(!isAddMemInstrWithRelocation(MI) &&
+             "Unexpected NDD instruction with relocation!");
   }
 
   // NonNF -> NF only if it's not a compressible NDD instruction and eflags is

diff  --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index ca953d6008b27..ab6e6d0687b71 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -66,6 +66,8 @@ STATISTIC(NumTestsInserted, "Number of test instructions inserted");
 STATISTIC(NumAddsInserted, "Number of adds instructions inserted");
 STATISTIC(NumNFsConvertedTo, "Number of NF instructions converted to");
 
+extern cl::opt<bool> X86EnableAPXForRelocation;
+
 namespace {
 
 // Convenient array type for storing registers associated with each condition.
@@ -242,7 +244,15 @@ static EFLAGSClobber getClobberType(const MachineInstr &MI) {
       MI.findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr);
   if (!FlagDef)
     return NoClobber;
-  if (FlagDef->isDead() && X86::getNFVariant(MI.getOpcode()))
+
+  // For the instructions are ADDrm/ADDmr with relocation, we'll skip the
+  // optimization for replacing non-NF with NF. This is to keep backward
+  // compatiblity with old version of linkers without APX relocation type
+  // support on Linux OS.
+  bool IsWithReloc =
+      X86EnableAPXForRelocation ? false : isAddMemInstrWithRelocation(MI);
+
+  if (FlagDef->isDead() && X86::getNFVariant(MI.getOpcode()) && !IsWithReloc)
     return EvitableClobber;
 
   return InevitableClobber;

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index de29a76882148..5220ae2e67bb6 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -53,6 +53,8 @@ using namespace llvm;
 #define GET_INSTRINFO_CTOR_DTOR
 #include "X86GenInstrInfo.inc"
 
+extern cl::opt<bool> X86EnableAPXForRelocation;
+
 static cl::opt<bool>
     NoFusing("disable-spill-fusing",
              cl::desc("Disable fusing of spill code into instructions"),
@@ -102,22 +104,8 @@ 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;
-  }
+  const X86RegisterInfo *RI = Subtarget.getRegisterInfo();
+  return RI->constrainRegClassToNonRex2(RC);
 }
 
 bool X86InstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
@@ -5464,8 +5452,16 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
           continue;
         }
 
+        // For the instructions are ADDrm/ADDmr with relocation, we'll skip the
+        // optimization for replacing non-NF with NF. This is to keep backward
+        // compatiblity with old version of linkers without APX relocation type
+        // support on Linux OS.
+        bool IsWithReloc = X86EnableAPXForRelocation
+                               ? false
+                               : isAddMemInstrWithRelocation(Inst);
+
         // Try to replace non-NF with NF instructions.
-        if (HasNF && Inst.registerDefIsDead(X86::EFLAGS, TRI)) {
+        if (HasNF && Inst.registerDefIsDead(X86::EFLAGS, TRI) && !IsWithReloc) {
           unsigned NewOp = X86::getNFVariant(Inst.getOpcode());
           if (!NewOp)
             return false;

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h
index 9ca2737686c09..2a9f567689ecb 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/llvm/lib/Target/X86/X86InstrInfo.h
@@ -174,6 +174,19 @@ inline static bool isMem(const MachineInstr &MI, unsigned Op) {
          MI.getOperand(Op + X86::AddrSegmentReg).isReg() && isLeaMem(MI, Op);
 }
 
+inline static bool isAddMemInstrWithRelocation(const MachineInstr &MI) {
+  unsigned Op = MI.getOpcode();
+  if (Op == X86::ADD64rm || Op == X86::ADD64mr_ND || Op == X86::ADD64rm_ND) {
+    int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
+                  X86II::getOperandBias(MI.getDesc());
+    const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
+    if (MO.getTargetFlags() == X86II::MO_GOTTPOFF)
+      return true;
+  }
+
+  return false;
+}
+
 class X86InstrInfo final : public X86GenInstrInfo {
   X86Subtarget &Subtarget;
   const X86RegisterInfo RI;

diff  --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 1c4114f8cc9c6..29242c7059d5f 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -1237,3 +1237,23 @@ bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
 
   return true;
 }
+
+const TargetRegisterClass *X86RegisterInfo::constrainRegClassToNonRex2(
+    const TargetRegisterClass *RC) const {
+  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;
+  }
+}

diff  --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h
index 5b6ac3c5da019..b3c03e8f2bc22 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.h
+++ b/llvm/lib/Target/X86/X86RegisterInfo.h
@@ -171,6 +171,9 @@ class X86RegisterInfo final : public X86GenRegisterInfo {
                              SmallVectorImpl<MCPhysReg> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
+
+  const TargetRegisterClass *
+  constrainRegClassToNonRex2(const TargetRegisterClass *RC) const;
 };
 
 } // End llvm namespace

diff  --git a/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp b/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
new file mode 100644
index 0000000000000..fe7a49ab4771d
--- /dev/null
+++ b/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
@@ -0,0 +1,232 @@
+//===- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This pass is added to suppress APX features for relocations. It's used to
+/// keep backward compatibility with old version of linker having no APX
+/// support. It can be removed after APX support is included in the default
+/// linker on OS.
+///
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "X86InstrInfo.h"
+#include "X86RegisterInfo.h"
+#include "X86Subtarget.h"
+
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "x86-suppress-apx-for-relocation"
+
+cl::opt<bool> X86EnableAPXForRelocation(
+    "x86-enable-apx-for-relocation",
+    cl::desc("Enable APX features (EGPR, NDD and NF) for instructions with "
+             "relocations on x86-64 ELF"),
+    cl::init(false));
+
+namespace {
+class X86SuppressAPXForRelocationPass : public MachineFunctionPass {
+public:
+  X86SuppressAPXForRelocationPass() : MachineFunctionPass(ID) {}
+
+  StringRef getPassName() const override {
+    return "X86 Suppress APX features for relocation";
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  static char ID;
+};
+} // namespace
+
+char X86SuppressAPXForRelocationPass::ID = 0;
+
+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,
+                                 const X86Subtarget &ST, unsigned int OpNum) {
+  MachineRegisterInfo *MRI = &MF.getRegInfo();
+  Register Reg = MI.getOperand(OpNum).getReg();
+  if (!Reg.isVirtual()) {
+    assert(!X86II::isApxExtendedReg(Reg) && "APX EGPR is used unexpectedly.");
+    return;
+  }
+  const TargetRegisterClass *RC = MRI->getRegClass(Reg);
+  const X86RegisterInfo *RI = ST.getRegisterInfo();
+  const TargetRegisterClass *NewRC = RI->constrainRegClassToNonRex2(RC);
+  MRI->setRegClass(Reg, NewRC);
+}
+
+static bool handleInstructionWithEGPR(MachineFunction &MF,
+                                      const X86Subtarget &ST) {
+  if (!ST.hasEGPR())
+    return false;
+
+  auto suppressEGPRInInstrWithReloc = [&](MachineInstr &MI,
+                                          ArrayRef<unsigned> OpNoArray) {
+    int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
+                  X86II::getOperandBias(MI.getDesc());
+    const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
+    if (MO.getTargetFlags() == X86II::MO_GOTTPOFF ||
+        MO.getTargetFlags() == X86II::MO_GOTPCREL) {
+      LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n  "
+                        << MI);
+      for (unsigned OpNo : OpNoArray)
+        suppressEGPRRegClass(MF, MI, ST, OpNo);
+      LLVM_DEBUG(dbgs() << "to:\n  " << MI << "\n");
+    }
+  };
+
+  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::TEST32mr:
+      case X86::TEST64mr: {
+        suppressEGPRInInstrWithReloc(MI, {5});
+        break;
+      }
+      case X86::CMP32rm:
+      case X86::CMP64rm:
+      case X86::MOV32rm:
+      case X86::MOV64rm: {
+        suppressEGPRInInstrWithReloc(MI, {0});
+        break;
+      }
+      case X86::ADC32rm:
+      case X86::ADD32rm:
+      case X86::AND32rm:
+      case X86::OR32rm:
+      case X86::SBB32rm:
+      case X86::SUB32rm:
+      case X86::XOR32rm:
+      case X86::ADC64rm:
+      case X86::ADD64rm:
+      case X86::AND64rm:
+      case X86::OR64rm:
+      case X86::SBB64rm:
+      case X86::SUB64rm:
+      case X86::XOR64rm: {
+        suppressEGPRInInstrWithReloc(MI, {0, 1});
+        break;
+      }
+      }
+    }
+  }
+  return true;
+}
+
+static bool handleNDDOrNFInstructions(MachineFunction &MF,
+                                      const X86Subtarget &ST) {
+  if (!ST.hasNDD() && !ST.hasNF())
+    return false;
+
+  const X86InstrInfo *TII = ST.getInstrInfo();
+  MachineRegisterInfo *MRI = &MF.getRegInfo();
+  for (MachineBasicBlock &MBB : MF) {
+    for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
+      unsigned Opcode = MI.getOpcode();
+      switch (Opcode) {
+      case X86::ADD64rm_NF:
+      case X86::ADD64mr_NF_ND:
+      case X86::ADD64rm_NF_ND:
+        llvm_unreachable("Unexpected NF instruction!");
+      case X86::ADD64rm_ND: {
+        int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
+                      X86II::getOperandBias(MI.getDesc());
+        const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
+        if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
+          LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n  "
+                            << MI);
+          Register Reg = MRI->createVirtualRegister(&X86::GR64_NOREX2RegClass);
+          [[maybe_unused]] MachineInstrBuilder CopyMIB =
+              BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
+                      Reg)
+                  .addReg(MI.getOperand(1).getReg());
+          MI.getOperand(1).setReg(Reg);
+          const MCInstrDesc &NewDesc = TII->get(X86::ADD64rm);
+          MI.setDesc(NewDesc);
+          suppressEGPRRegClass(MF, MI, ST, 0);
+          MI.tieOperands(0, 1);
+          LLVM_DEBUG(dbgs() << "to:\n  " << *CopyMIB << "\n");
+          LLVM_DEBUG(dbgs() << "  " << MI << "\n");
+        }
+        break;
+      }
+      case X86::ADD64mr_ND: {
+        int MemRefBegin = X86II::getMemoryOperandNo(MI.getDesc().TSFlags);
+        const MachineOperand &MO = MI.getOperand(MemRefBegin + X86::AddrDisp);
+        if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
+          LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n  "
+                            << MI);
+          suppressEGPRRegClass(MF, MI, ST, 0);
+          Register Reg = MRI->createVirtualRegister(&X86::GR64_NOREX2RegClass);
+          [[maybe_unused]] MachineInstrBuilder CopyMIB =
+              BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
+                      Reg)
+                  .addReg(MI.getOperand(6).getReg());
+          MachineInstrBuilder NewMIB =
+              BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(X86::ADD64rm),
+                      MI.getOperand(0).getReg())
+                  .addReg(Reg)
+                  .addReg(MI.getOperand(1).getReg())
+                  .addImm(MI.getOperand(2).getImm())
+                  .addReg(MI.getOperand(3).getReg())
+                  .add(MI.getOperand(4))
+                  .addReg(MI.getOperand(5).getReg());
+          MachineOperand *FlagDef =
+              MI.findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr);
+          if (FlagDef && FlagDef->isDead()) {
+            MachineOperand *NewFlagDef =
+                NewMIB->findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr);
+            if (NewFlagDef)
+              NewFlagDef->setIsDead();
+          }
+          MI.eraseFromParent();
+          LLVM_DEBUG(dbgs() << "to:\n  " << *CopyMIB << "\n");
+          LLVM_DEBUG(dbgs() << "  " << *NewMIB << "\n");
+        }
+        break;
+      }
+      }
+    }
+  }
+  return true;
+}
+
+bool X86SuppressAPXForRelocationPass::runOnMachineFunction(
+    MachineFunction &MF) {
+  if (X86EnableAPXForRelocation)
+    return false;
+  const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
+  bool Changed = handleInstructionWithEGPR(MF, ST);
+  Changed |= handleNDDOrNFInstructions(MF, ST);
+
+  return Changed;
+}
\ No newline at end of file

diff  --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 5301b397e2d39..975b94c18fb7f 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) {
@@ -559,6 +560,8 @@ void X86PassConfig::addPreRegAlloc() {
     addPass(createX86AvoidStoreForwardingBlocks());
   }
 
+  addPass(createX86SuppressAPXForRelocationPass());
+
   addPass(createX86SpeculativeLoadHardeningPass());
   addPass(createX86FlagsCopyLoweringPass());
   addPass(createX86DynAllocaExpander());

diff  --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll
index 6d824f8b510af..0fbfb42d2a4dd 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -41,6 +41,7 @@
 ; CHECK-NEXT:       Argument Stack Rebase
 ; CHECK-NEXT:       Finalize ISel and expand pseudo-instructions
 ; CHECK-NEXT:       Local Stack Slot Allocation
+; CHECK-NEXT:       X86 Suppress APX features for relocation
 ; CHECK-NEXT:       X86 speculative load hardening
 ; CHECK-NEXT:       X86 EFLAGS copy lowering
 ; CHECK-NEXT:       X86 DynAlloca Expander

diff  --git a/llvm/test/CodeGen/X86/apx/add.ll b/llvm/test/CodeGen/X86/apx/add.ll
index 2641fd7c14141..86343811901a9 100644
--- a/llvm/test/CodeGen/X86/apx/add.ll
+++ b/llvm/test/CodeGen/X86/apx/add.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @add8rr(i8 noundef %a, i8 noundef %b) {
 ; CHECK-LABEL: add8rr:

diff  --git a/llvm/test/CodeGen/X86/apx/and.ll b/llvm/test/CodeGen/X86/apx/and.ll
index 23aed77b948b9..3379ac9dec893 100644
--- a/llvm/test/CodeGen/X86/apx/and.ll
+++ b/llvm/test/CodeGen/X86/apx/and.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @and8rr(i8 noundef %a, i8 noundef %b) {
 ; CHECK-LABEL: and8rr:

diff  --git a/llvm/test/CodeGen/X86/apx/compress-evex.mir b/llvm/test/CodeGen/X86/apx/compress-evex.mir
index 7723cac8eb326..c0ecfac06aa75 100644
--- a/llvm/test/CodeGen/X86/apx/compress-evex.mir
+++ b/llvm/test/CodeGen/X86/apx/compress-evex.mir
@@ -1,5 +1,6 @@
 # RUN: llc %s -mtriple=x86_64-unknown -mattr=+ndd,+egpr -start-before=x86-compress-evex -show-mc-encoding -o - | FileCheck --check-prefixes=CHECK,NDD %s
 # RUN: llc %s -mtriple=x86_64-unknown -mattr=+ndd,+egpr,+nf -start-before=x86-compress-evex -show-mc-encoding -o - | FileCheck --check-prefixes=CHECK,NDD-NF %s
+# RUN: llc %s -mtriple=x86_64-unknown -mattr=+ndd,+egpr,+nf -x86-enable-apx-for-relocation=true -start-before=x86-compress-evex -show-mc-encoding -o - | FileCheck --check-prefixes=CHECK,NDD-NF %s
 
 ...
 ---

diff  --git a/llvm/test/CodeGen/X86/apx/dec.ll b/llvm/test/CodeGen/X86/apx/dec.ll
index 56c4533629186..a4b54d59b309d 100644
--- a/llvm/test/CodeGen/X86/apx/dec.ll
+++ b/llvm/test/CodeGen/X86/apx/dec.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs | FileCheck --check-prefix=NF %s
 
 define i8 @dec8r(i8 noundef %a) {
 ; CHECK-LABEL: dec8r:

diff  --git a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
index bd764c2edef29..0dcda8efdbc78 100644
--- a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
+++ b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+nf | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+nf -x86-enable-apx-for-relocation=true | FileCheck %s
 
 define i32 @flag_copy_1(i32 %x, i32 %y, ptr %pz) nounwind {
 ; CHECK-LABEL: flag_copy_1:

diff  --git a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
index 4002906795dc8..a78e051fe65f5 100644
--- a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
+++ b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
@@ -1,6 +1,8 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc  -mtriple=x86_64 -run-pass x86-flags-copy-lowering -mattr=+ndd -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,NDD %s
 # RUN: llc  -mtriple=x86_64 -run-pass x86-flags-copy-lowering -mattr=+ndd,+nf -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,NDD-NF %s
+# RUN: llc  -mtriple=x86_64 -run-pass x86-flags-copy-lowering -mattr=+ndd,+nf -x86-enable-apx-for-relocation=true -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,NDD-NF %s
+
 # Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.
 
 ...

diff  --git a/llvm/test/CodeGen/X86/apx/imul.ll b/llvm/test/CodeGen/X86/apx/imul.ll
index d97b2c0baec5e..34cc9a90708bd 100644
--- a/llvm/test/CodeGen/X86/apx/imul.ll
+++ b/llvm/test/CodeGen/X86/apx/imul.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs | FileCheck --check-prefix=NF %s
 
 define i16 @mul16rr(i16 noundef %a, i16 noundef %b) {
 ; CHECK-LABEL: mul16rr:

diff  --git a/llvm/test/CodeGen/X86/apx/inc.ll b/llvm/test/CodeGen/X86/apx/inc.ll
index cecb65261bf81..671edf83a2b96 100644
--- a/llvm/test/CodeGen/X86/apx/inc.ll
+++ b/llvm/test/CodeGen/X86/apx/inc.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs | FileCheck --check-prefix=NF %s
 
 define i8 @inc8r(i8 noundef %a) {
 ; CHECK-LABEL: inc8r:

diff  --git a/llvm/test/CodeGen/X86/apx/neg.ll b/llvm/test/CodeGen/X86/apx/neg.ll
index cf86dc609bc33..8f8a391487b5a 100644
--- a/llvm/test/CodeGen/X86/apx/neg.ll
+++ b/llvm/test/CodeGen/X86/apx/neg.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @neg8r(i8 noundef %a) {
 ; CHECK-LABEL: neg8r:

diff  --git a/llvm/test/CodeGen/X86/apx/or.ll b/llvm/test/CodeGen/X86/apx/or.ll
index 995946c007dca..12ee5fc3404db 100644
--- a/llvm/test/CodeGen/X86/apx/or.ll
+++ b/llvm/test/CodeGen/X86/apx/or.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @or8rr(i8 noundef %a, i8 noundef %b) {
 ; CHECK-LABEL: or8rr:

diff  --git a/llvm/test/CodeGen/X86/apx/reloc.mir b/llvm/test/CodeGen/X86/apx/reloc.mir
new file mode 100644
index 0000000000000..9009f5b1a669c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/reloc.mir
@@ -0,0 +1,296 @@
+# RUN: llc -mattr=+egpr,+ndd -x mir < %s -x86-enable-apx-for-relocation=true -run-pass x86-suppress-apx-for-relocation -verify-machineinstrs -o - | FileCheck %s --check-prefixes=CHECK,APXREL
+# RUN: llc -mattr=+egpr,+ndd -x mir < %s -run-pass x86-suppress-apx-for-relocation -verify-machineinstrs -o - | FileCheck %s --check-prefixes=CHECK,NOAPXREL
+
+
+--- |
+  target triple = "x86_64-unknown-linux-gnu"
+
+  @x = external global i64
+  @i = external thread_local global i32
+
+  define i32 @mov() {
+  entry:
+    ret i32 undef
+  }
+
+  define i8 @test() {
+  entry:
+    ret i8 undef
+  }
+  define i32 @adc() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @add() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @and() {
+  entry:
+    ret i32 undef
+  }
+
+  define i8 @cmp() {
+  entry:
+    ret i8 undef
+  }
+
+  define i32 @or() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @sbb() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @sub() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @xor() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @add64rm_nd() {
+  entry:
+    ret i32 undef
+  }
+
+  define i32 @add64mr_nd() {
+  entry:
+    ret i32 undef
+  }
+...
+---
+name: mov
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load (s64))
+    %1:gr32 = MOV32rm killed %0, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %1
+    RET 0, $eax
+
+# CHECK: name: mov
+# APXREL: %0:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load (s64))
+# NOAPXREL: %0:gr64_norex2 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load (s64))
+...
+---
+name: test
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr8 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    TEST64mr $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, %0:gr64, implicit-def $eflags :: (load (s64))
+    %1:gr8 = SETCCr 5, implicit $eflags
+    $al = COPY %1
+    RET 0, $al
+
+# CHECK: name: test
+# APXREL: %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+# APXREL-NEXT: TEST64mr $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, %0, implicit-def $eflags :: (load (s64))
+# NOAPXREL: %0:gr64_norex2 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+# NOAPXREL-NEXT: TEST64mr $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, %0, implicit-def $eflags :: (load (s64))
+
+...
+---
+name: adc
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr64 }
+  - { id: 3, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = OR64ri8 %0, 7, implicit-def $eflags
+    %2:gr64 = ADC64rm %1, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags, implicit $eflags :: (load (s64))
+    %3:gr32 = MOV32rm killed %2, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %3
+    RET 0, $eax
+
+# CHECK: name: adc
+# APXREL: %2:gr64 = ADC64rm %1, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags, implicit $eflags :: (load (s64))
+# NOAPXREL: %2:gr64_norex2 = ADC64rm %1, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags, implicit $eflags :: (load (s64))
+...
+---
+name: add
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = ADD64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+# CHECK: name: add
+# APXREL: %1:gr64 = ADD64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+# NOAPXREL: %1:gr64_norex2 = ADD64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+...
+---
+name: and
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = AND64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+
+# CHECK: name: and
+# APXREL: %1:gr64 = AND64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+# NOAPXREL: %1:gr64_norex2 = AND64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+...
+---
+name: or
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = OR64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+
+# CHECK: name: or
+# APXREL: %1:gr64 = OR64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+# NOAPXREL: %1:gr64_norex2 = OR64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+...
+---
+name: sbb
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr64 }
+  - { id: 3, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = OR64ri8 %0, 7, implicit-def $eflags
+    %2:gr64 = SBB64rm %1, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags, implicit $eflags :: (load (s64))
+    %3:gr32 = MOV32rm killed %2, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %3
+    RET 0, $eax
+
+# CHECK: name: sbb
+# APXREL: %1:gr64 = OR64ri8 %0, 7, implicit-def $eflags
+# APXREL-NEXT: %2:gr64 = SBB64rm %1, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags, implicit $eflags :: (load (s64))
+# NOAPXREL: %1:gr64_norex2 = OR64ri8 %0, 7, implicit-def $eflags
+# NOAPXREL-NEXT: %2:gr64_norex2 = SBB64rm %1, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags, implicit $eflags :: (load (s64))
+...
+---
+name: sub
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = SUB64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+
+# CHECK: name: sub
+# APXREL: %1:gr64 = SUB64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+# NOAPXREL: %1:gr64_norex2 = SUB64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+...
+---
+name: xor
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = XOR64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+
+# CHECK: name: xor
+# APXREL: %1:gr64 = XOR64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+# NOAPXREL: %1:gr64_norex2 = XOR64rm %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def $eflags :: (load (s64))
+...
+---
+name: add64rm_nd
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = ADD64rm_ND %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def dead $eflags :: (load (s64) from got)
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+
+# CHECK: name: add64rm_nd
+# APXREL: %1:gr64 = ADD64rm_ND %0, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def dead $eflags :: (load (s64) from got)
+# NOAPXREL: %3:gr64_norex2 = COPY %0
+# NOAPXREL: %1:gr64_norex2 = ADD64rm %3, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def dead $eflags
+...
+---
+name: add64mr_nd
+alignment: 16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr64 }
+  - { id: 1, class: gr64 }
+  - { id: 2, class: gr32 }
+body: |
+  bb.0.entry:
+    %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load (s64))
+    %1:gr64 = ADD64mr_ND $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, %0, implicit-def dead $eflags :: (load (s64) from got)
+    %2:gr32 = MOV32rm killed %1, 1, $noreg, 0, $fs :: (load (s32))
+    $eax = COPY %2
+    RET 0, $eax
+
+# CHECK: name: add64mr_nd
+# APXREL: %1:gr64 = ADD64mr_ND $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, %0, implicit-def dead $eflags :: (load (s64) from got)
+# NOAPXREL: %3:gr64_norex2 = COPY %0
+# NOAPXREL: %1:gr64_norex2 = ADD64rm %3, $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg, implicit-def dead $eflags
+...

diff  --git a/llvm/test/CodeGen/X86/apx/shl.ll b/llvm/test/CodeGen/X86/apx/shl.ll
index 1db01f2198929..896cd55bc7452 100644
--- a/llvm/test/CodeGen/X86/apx/shl.ll
+++ b/llvm/test/CodeGen/X86/apx/shl.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @shl8ri(i8 noundef %a) {
 ; CHECK-LABEL: shl8ri:

diff  --git a/llvm/test/CodeGen/X86/apx/shr.ll b/llvm/test/CodeGen/X86/apx/shr.ll
index a63d22b30f83d..b82000bd950dc 100644
--- a/llvm/test/CodeGen/X86/apx/shr.ll
+++ b/llvm/test/CodeGen/X86/apx/shr.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @shr8m1(ptr %ptr) {
 ; CHECK-LABEL: shr8m1:

diff  --git a/llvm/test/CodeGen/X86/apx/sub.ll b/llvm/test/CodeGen/X86/apx/sub.ll
index 9519fab4ee518..1864ca8279954 100644
--- a/llvm/test/CodeGen/X86/apx/sub.ll
+++ b/llvm/test/CodeGen/X86/apx/sub.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @sub8rr(i8 noundef %a, i8 noundef %b) {
 ; CHECK-LABEL: sub8rr:

diff  --git a/llvm/test/CodeGen/X86/apx/tls.ll b/llvm/test/CodeGen/X86/apx/tls.ll
new file mode 100644
index 0000000000000..736e843dc1a26
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/tls.ll
@@ -0,0 +1,76 @@
+; 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
+; 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-enable-apx-for-relocation=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
+
+
+; TLSDESC: d5 18 89 c0       movq %rax, %r16
+; TLSDESC-NEXT: 48 8d 05 00 00 00 00       leaq (%rip), %rax
+; TLSDESC-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_LD_APXRELAX: d5 18 c7 c0 fc ff ff ff       movq $-4, %r16
+
+; GOTTPOFF_NOAPXRELAX: 48 8b 1d 00 00 00 00       movq (%rip), %rbx
+; GOTTPOFF_NOAPXRELAX-NEXT: R_X86_64_GOTTPOFF j-0x4
+; GOTTPOFF_LD_NOAPXRELAX: 48 c7 c3 fc ff ff ff       movq $-4, %rbx
+
+ at a = thread_local global i32 0, align 4
+ at b = external thread_local global i32, align 4
+ at c = external thread_local global i32, align 4
+ at d = external thread_local global i32, align 4
+ at e = external thread_local global i32, align 4
+ at f = external thread_local global i32, align 4
+ at g = external thread_local global i32, align 4
+ at h = external thread_local global i32, align 4
+ at i = external thread_local global i32, align 4
+ at 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/apx/xor.ll b/llvm/test/CodeGen/X86/apx/xor.ll
index d908849e2848f..e083c6580398c 100644
--- a/llvm/test/CodeGen/X86/apx/xor.ll
+++ b/llvm/test/CodeGen/X86/apx/xor.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs --show-mc-encoding | FileCheck %s
 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd,nf -x86-enable-apx-for-relocation=true -verify-machineinstrs --show-mc-encoding | FileCheck --check-prefix=NF %s
 
 define i8 @xor8rr(i8 noundef %a, i8 noundef %b) {
 ; CHECK-LABEL: xor8rr:

diff  --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll
index d72f517cfb603..540046e6a8638 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -127,6 +127,7 @@
 ; CHECK-NEXT:       X86 LEA Optimize
 ; CHECK-NEXT:       X86 Optimize Call Frame
 ; CHECK-NEXT:       X86 Avoid Store Forwarding Block
+; CHECK-NEXT:       X86 Suppress APX features for relocation
 ; CHECK-NEXT:       X86 speculative load hardening
 ; CHECK-NEXT:       X86 EFLAGS copy lowering
 ; CHECK-NEXT:       X86 DynAlloca Expander


        


More information about the llvm-commits mailing list