mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 23:49:22 +08:00
[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@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 ```
This commit is contained in:
@@ -78,6 +78,7 @@ set(sources
|
||||
X86SpeculativeLoadHardening.cpp
|
||||
X86SpeculativeExecutionSideEffectSuppression.cpp
|
||||
X86Subtarget.cpp
|
||||
X86SuppressAPXForReloc.cpp
|
||||
X86TargetMachine.cpp
|
||||
X86TargetObjectFile.cpp
|
||||
X86TargetTransformInfo.cpp
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +171,9 @@ public:
|
||||
SmallVectorImpl<MCPhysReg> &Hints,
|
||||
const MachineFunction &MF, const VirtRegMap *VRM,
|
||||
const LiveRegMatrix *Matrix) const override;
|
||||
|
||||
const TargetRegisterClass *
|
||||
constrainRegClassToNonRex2(const TargetRegisterClass *RC) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
232
llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
Normal file
232
llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
...
|
||||
---
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
...
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
296
llvm/test/CodeGen/X86/apx/reloc.mir
Normal file
296
llvm/test/CodeGen/X86/apx/reloc.mir
Normal file
@@ -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
|
||||
...
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
76
llvm/test/CodeGen/X86/apx/tls.ll
Normal file
76
llvm/test/CodeGen/X86/apx/tls.ll
Normal file
@@ -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
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user