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 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 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 459e15031ee16..72da49d6ec424 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 X86EnableAPXForRelocation; + static cl::opt 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, @@ -5480,8 +5468,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 &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 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 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(); + 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 4cecbbf27aa30..4bbd49b91dfc5 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 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 + +@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/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