Revert "Liveness Analysis Pass"

This reverts commit r197254.

This was an accidental merge of Juergen's patch. It will be checked in
shortly, but wasn't meant to go in quite yet.

Conflicts:
	include/llvm/CodeGen/StackMaps.h
	lib/CodeGen/StackMaps.cpp
	test/CodeGen/X86/stackmap-liveness.ll

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197260 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2013-12-13 18:57:20 +00:00
parent f343bc9956
commit 38c9ecda9b
16 changed files with 52 additions and 508 deletions

View File

@ -145,10 +145,6 @@ class MachineFrameInfo {
/// to builtin \@llvm.returnaddress.
bool ReturnAddressTaken;
/// HasStackmap - This boolean keeps track of whether there is a call
/// to builtin \@llvm.experimental.stackmap or \@llvm.experimental.patchpoint.
bool HasStackMap;
/// StackSize - The prolog/epilog code inserter calculates the final stack
/// offsets for all of the fixed size objects, updating the Objects list
/// above. It then updates StackSize to contain the number of bytes that need
@ -239,7 +235,6 @@ public:
HasVarSizedObjects = false;
FrameAddressTaken = false;
ReturnAddressTaken = false;
HasStackMap = false;
AdjustsStack = false;
HasCalls = false;
StackProtectorIdx = -1;
@ -285,12 +280,6 @@ public:
bool isReturnAddressTaken() const { return ReturnAddressTaken; }
void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; }
/// hasStackMap - This method may be called any time after instruction
/// selection is complete to determine if there is a call to builtin
/// \@llvm.experimental.stackmap or \@llvm.experimental.patchpoint.
bool hasStackMap() const { return HasStackMap; }
void setHasStackMap(bool s = true) { HasStackMap = s; }
/// getObjectIndexBegin - Return the minimum frame object index.
///
int getObjectIndexBegin() const { return -NumFixedObjects; }

View File

@ -426,15 +426,6 @@ public:
OperandRecycler.deallocate(Cap, Array);
}
/// \brief Allocate and initialize a register mask with @p NumRegister bits.
uint32_t *allocateRegisterMask(unsigned NumRegister) {
unsigned Size = (NumRegister + 31) / 32;
uint32_t *Mask = Allocator.Allocate<uint32_t>(Size);
for (unsigned i = 0; i != Size; ++i)
Mask[i] = 0;
return Mask;
}
/// allocateMemRefsArray - Allocate an array to hold MachineMemOperand
/// pointers. This array is owned by the MachineFunction.
MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num);

View File

@ -56,7 +56,6 @@ public:
MO_GlobalAddress, ///< Address of a global value
MO_BlockAddress, ///< Address of a basic block
MO_RegisterMask, ///< Mask of preserved registers.
MO_RegisterLiveOut, ///< Mask of live-out registers.
MO_Metadata, ///< Metadata reference (for debug info)
MO_MCSymbol ///< MCSymbol reference (for debug/eh info)
};
@ -154,7 +153,7 @@ private:
const ConstantFP *CFP; // For MO_FPImmediate.
const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit.
int64_t ImmVal; // For MO_Immediate.
const uint32_t *RegMask; // For MO_RegisterMask and MO_RegisterLiveOut.
const uint32_t *RegMask; // For MO_RegisterMask.
const MDNode *MD; // For MO_Metadata.
MCSymbol *Sym; // For MO_MCSymbol
@ -247,8 +246,6 @@ public:
bool isBlockAddress() const { return OpKind == MO_BlockAddress; }
/// isRegMask - Tests if this is a MO_RegisterMask operand.
bool isRegMask() const { return OpKind == MO_RegisterMask; }
/// isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.
bool isRegLiveOut() const { return OpKind == MO_RegisterLiveOut; }
/// isMetadata - Tests if this is a MO_Metadata operand.
bool isMetadata() const { return OpKind == MO_Metadata; }
bool isMCSymbol() const { return OpKind == MO_MCSymbol; }
@ -479,12 +476,6 @@ public:
return Contents.RegMask;
}
/// getRegLiveOut - Returns a bit mask of live-out registers.
const uint32_t *getRegLiveOut() const {
assert(isRegLiveOut() && "Wrong MachineOperand accessor");
return Contents.RegMask;
}
const MDNode *getMetadata() const {
assert(isMetadata() && "Wrong MachineOperand accessor");
return Contents.MD;
@ -668,12 +659,6 @@ public:
Op.Contents.RegMask = Mask;
return Op;
}
static MachineOperand CreateRegLiveOut(const uint32_t *Mask) {
assert(Mask && "Missing live-out register mask");
MachineOperand Op(MachineOperand::MO_RegisterLiveOut);
Op.Contents.RegMask = Mask;
return Op;
}
static MachineOperand CreateMetadata(const MDNode *Meta) {
MachineOperand Op(MachineOperand::MO_Metadata);
Op.Contents.MD = Meta;

View File

@ -568,11 +568,6 @@ namespace llvm {
/// bundles (created earlier, e.g. during pre-RA scheduling).
extern char &FinalizeMachineBundlesID;
/// StackMapLiveness - This pass analyses the register live-out set of
/// stackmap/patchpoint intrinsics and attaches the calculated information to
/// the intrinsic for later emission to the StackMap.
extern char &StackMapLivenessID;
} // End llvm namespace
#endif

View File

@ -1,67 +0,0 @@
//===--- StackMapLivenessAnalysis - StackMap Liveness Analysis --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass calculates the liveness for each basic block in a function and
// attaches the register live-out information to a stackmap or patchpoint
// intrinsic if present.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H
#define LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
namespace llvm {
/// \brief This pass calculates the liveness information for each basic block in
/// a function and attaches the register live-out information to a stackmap or
/// patchpoint intrinsic if present.
///
/// This is an optional pass that has to be explicitely enabled via the
/// -enable-stackmap-liveness flag. The pass skips functions that don't have any
/// stackmap or patchpoint intrinsics. The information provided by this pass is
/// optional and not required by the aformentioned intrinsics to function.
class StackMapLiveness : public MachineFunctionPass {
MachineFunction *MF;
const TargetRegisterInfo *TRI;
LivePhysRegs LiveRegs;
public:
static char ID;
/// \brief Default construct and initialize the pass.
StackMapLiveness();
/// \brief Tell the pass manager which passes we depend on and what
/// information we preserve.
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
/// \brief Calculate the liveness information for the given machine function.
virtual bool runOnMachineFunction(MachineFunction &MF);
private:
/// \brief Performs the actual liveness calculation for the function.
bool calculateLiveness();
/// \brief Add the current register live set to the instruction.
void addLiveOutSetToMI(MachineInstr &MI);
/// \brief Create a register mask and initialize it with the registers from
/// the register live set.
uint32_t *createRegisterMask() const;
/// \brief Print the current register live set for debugging.
void printLiveOutSet(raw_ostream &OS) const;
};
} // end llvm namespace
#endif // end LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H

View File

@ -93,20 +93,6 @@ public:
: LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}
};
struct LiveOutReg {
unsigned short Reg;
unsigned short RegNo;
unsigned short Size;
LiveOutReg() : Reg(0), RegNo(0), Size(0) {}
LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size)
: Reg(Reg), RegNo(RegNo), Size(Size) {}
// Only sort by the dwarf register number.
bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; }
static bool isInvalid(const LiveOutReg &LO) { return LO.Reg == 0; }
};
// OpTypes are used to encode information about the following logical
// operand (which may consist of several MachineOperands) for the
// OpParser.
@ -129,18 +115,15 @@ public:
private:
typedef SmallVector<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
struct CallsiteInfo {
const MCExpr *CSOffsetExpr;
uint64_t ID;
LocationVec Locations;
LiveOutVec LiveOuts;
CallsiteInfo() : CSOffsetExpr(0), ID(0) {}
CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
LocationVec &Locations, LiveOutVec &LiveOuts)
: CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations),
LiveOuts(LiveOuts) {}
LocationVec Locations)
: CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {}
};
typedef std::vector<CallsiteInfo> CallsiteInfoList;
@ -171,15 +154,8 @@ private:
std::pair<Location, MachineInstr::const_mop_iterator>
parseOperand(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) const;
MachineInstr::const_mop_iterator MOE);
/// \brief Create a live-out register record for the given register @p Reg.
LiveOutReg createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI,
const TargetRegisterInfo *TRI) const;
/// \brief Parse the register live-out mask and return a vector of live-out
/// registers that need to be recorded in the stackmap.
LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
/// This should be called by the MC lowering code _immediately_ before
/// lowering the MI to an MCInst. It records where the operands for the

View File

@ -266,7 +266,6 @@ void initializeLoopVectorizePass(PassRegistry&);
void initializeSLPVectorizerPass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&);
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
void initializeStackMapLivenessPass(PassRegistry&);
}
#endif

View File

@ -97,7 +97,6 @@ add_llvm_library(LLVMCodeGen
StackColoring.cpp
StackProtector.cpp
StackSlotColoring.cpp
StackMapLivenessAnalysis.cpp
StackMaps.cpp
TailDuplication.cpp
TargetFrameLoweringImpl.cpp

View File

@ -69,7 +69,6 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeVirtRegRewriterPass(Registry);
initializeLowerIntrinsicsPass(Registry);
initializeMachineFunctionPrinterPassPass(Registry);
initializeStackMapLivenessPass(Registry);
}
void LLVMInitializeCodeGen(LLVMPassRegistryRef R) {

View File

@ -199,8 +199,7 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
case MachineOperand::MO_BlockAddress:
return getBlockAddress() == Other.getBlockAddress() &&
getOffset() == Other.getOffset();
case MachineOperand::MO_RegisterMask:
case MachineOperand::MO_RegisterLiveOut:
case MO_RegisterMask:
return getRegMask() == Other.getRegMask();
case MachineOperand::MO_MCSymbol:
return getMCSymbol() == Other.getMCSymbol();
@ -242,7 +241,6 @@ hash_code llvm::hash_value(const MachineOperand &MO) {
return hash_combine(MO.getType(), MO.getTargetFlags(),
MO.getBlockAddress(), MO.getOffset());
case MachineOperand::MO_RegisterMask:
case MachineOperand::MO_RegisterLiveOut:
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask());
case MachineOperand::MO_Metadata:
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata());
@ -370,9 +368,6 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const {
case MachineOperand::MO_RegisterMask:
OS << "<regmask>";
break;
case MachineOperand::MO_RegisterLiveOut:
OS << "<regliveout>";
break;
case MachineOperand::MO_Metadata:
OS << '<';
WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);

View File

@ -69,8 +69,6 @@ static cl::opt<bool> DisableCGP("disable-cgp", cl::Hidden,
cl::desc("Disable Codegen Prepare"));
static cl::opt<bool> DisableCopyProp("disable-copyprop", cl::Hidden,
cl::desc("Disable Copy Propagation pass"));
static cl::opt<bool> EnableStackMapLiveness("enable-stackmap-liveness",
cl::Hidden, cl::desc("Enable StackMap Liveness Analysis Pass"));
static cl::opt<bool> PrintLSR("print-lsr-output", cl::Hidden,
cl::desc("Print LLVM IR produced by the loop-reduce pass"));
static cl::opt<bool> PrintISelInput("print-isel-input", cl::Hidden,
@ -538,9 +536,6 @@ void TargetPassConfig::addMachinePasses() {
if (addPreEmitPass())
printAndVerify("After PreEmit passes");
if (EnableStackMapLiveness)
addPass(&StackMapLivenessID);
}
/// Add passes that optimize machine instructions in SSA form.

View File

@ -6886,9 +6886,6 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
DAG.ReplaceAllUsesWith(Call, MN);
DAG.DeleteNode(Call);
// Inform the Frame Information that we have a stackmap in this function.
FuncInfo.MF->getFrameInfo()->setHasStackMap();
}
/// \brief Lower llvm.experimental.patchpoint directly to its target opcode.
@ -7028,9 +7025,6 @@ void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) {
} else
DAG.ReplaceAllUsesWith(Call, MN);
DAG.DeleteNode(Call);
// Inform the Frame Information that we have a stackmap in this function.
FuncInfo.MF->getFrameInfo()->setHasStackMap();
}
/// TargetLowering::LowerCallTo - This is the default LowerCallTo

View File

@ -1,128 +0,0 @@
//===-- StackMapLivenessAnalysis.cpp - StackMap live Out Analysis ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the StackMap Liveness analysis pass. The pass calculates
// the liveness for each basic block in a function and attaches the register
// live-out information to a stackmap or patchpoint intrinsic if present.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "stackmaps"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/StackMapLivenessAnalysis.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
STATISTIC(NumStackMapFuncVisited, "Number of functions visited");
STATISTIC(NumStackMapFuncSkipped, "Number of functions skipped");
STATISTIC(NumBBsVisited, "Number of basic blocks visited");
STATISTIC(NumBBsHaveNoStackmap, "Number of basic blocks with no stackmap");
STATISTIC(NumStackMaps, "Number of StackMaps visited");
char StackMapLiveness::ID = 0;
char &llvm::StackMapLivenessID = StackMapLiveness::ID;
INITIALIZE_PASS(StackMapLiveness, "stackmap-liveness",
"StackMap Liveness Analysis", false, false)
/// Default construct and initialize the pass.
StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) {
initializeStackMapLivenessPass(*PassRegistry::getPassRegistry());
}
/// Tell the pass manager which passes we depend on and what information we
/// preserve.
void StackMapLiveness::getAnalysisUsage(AnalysisUsage &AU) const {
// We preserve all information.
AU.setPreservesAll();
AU.setPreservesCFG();
// Default dependencie for all MachineFunction passes.
AU.addRequired<MachineFunctionAnalysis>();
}
/// Calculate the liveness information for the given machine function.
bool StackMapLiveness::runOnMachineFunction(MachineFunction &_MF) {
DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: "
<< _MF.getName() << " **********\n");
MF = &_MF;
TRI = MF->getTarget().getRegisterInfo();
++NumStackMapFuncVisited;
// Skip this function if there are no stackmaps.
if (!MF->getFrameInfo()->hasStackMap()) {
++NumStackMapFuncSkipped;
return false;
}
return calculateLiveness();
}
/// Performs the actual liveness calculation for the function.
bool StackMapLiveness::calculateLiveness() {
bool HasChanged = false;
// For all basic blocks in the function.
for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end();
MBBI != MBBE; ++MBBI) {
DEBUG(dbgs() << "****** BB " << MBBI->getName() << " ******\n");
LiveRegs.init(TRI);
LiveRegs.addLiveOuts(MBBI);
bool HasStackMap = false;
// Reverse iterate over all instructions and add the current live register
// set to an instruction if we encounter a stackmap or patchpoint
// instruction.
for (MachineBasicBlock::reverse_iterator I = MBBI->rbegin(),
E = MBBI->rend(); I != E; ++I) {
if (I->getOpcode() == TargetOpcode::STACKMAP ||
I->getOpcode() == TargetOpcode::PATCHPOINT) {
addLiveOutSetToMI(*I);
HasChanged = true;
HasStackMap = true;
++NumStackMaps;
}
LiveRegs.stepBackward(*I);
}
++NumBBsVisited;
if (!HasStackMap)
++NumBBsHaveNoStackmap;
}
return HasChanged;
}
/// Add the current register live set to the instruction.
void StackMapLiveness::addLiveOutSetToMI(MachineInstr &MI) {
uint32_t *Mask = createRegisterMask();
MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask);
MI.addOperand(*MF, MO);
DEBUG(dbgs() << " " << MI);
DEBUG(printLiveOutSet(dbgs()));
}
/// Create a register mask and initialize it with the registers from the
/// register live set.
uint32_t *StackMapLiveness::createRegisterMask() const {
// The mask is owned and cleaned up by the Machine Function.
uint32_t *Mask = MF->allocateRegisterMask(TRI->getNumRegs());
for (LivePhysRegs::const_iterator RI = LiveRegs.begin(), RE = LiveRegs.end();
RI != RE; ++RI)
Mask[*RI / 32] |= 1U << (*RI % 32);
return Mask;
}
/// Print the current register live set for debugging.
void StackMapLiveness::printLiveOutSet(raw_ostream &OS) const {
OS << " Register live-out:";
for (LivePhysRegs::const_iterator RI = LiveRegs.begin(), RE = LiveRegs.end();
RI != RE; ++RI)
OS << " " << TRI->getName(*RI);
OS << "\n";
}

View File

@ -68,10 +68,10 @@ unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) const {
MachineInstr::const_mop_iterator MOE) {
const MachineOperand &MOP = *MOI;
assert((!MOP.isReg() || !MOP.isImplicit()) &&
"Implicit operands should not be processed.");
assert(!MOP.isRegMask() && (!MOP.isReg() || !MOP.isImplicit()) &&
"Register mask and implicit operands should not be processed.");
if (MOP.isImm()) {
// Verify anyregcc
@ -106,9 +106,6 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
}
}
if (MOP.isRegMask() || MOP.isRegLiveOut())
return std::make_pair(Location(), ++MOI);
// Otherwise this is a reg operand. The physical register number will
// ultimately be encoded as a DWARF regno. The stack map also records the size
// of a spill slot that can hold the register content. (The runtime can
@ -123,66 +120,6 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
Location(Location::Register, RC->getSize(), MOP.getReg(), 0), ++MOI);
}
/// Go up the super-register chain until we hit a valid dwarf register number.
static short getDwarfRegNum(unsigned Reg, const MCRegisterInfo &MCRI,
const TargetRegisterInfo *TRI) {
int RegNo = MCRI.getDwarfRegNum(Reg, false);
for (MCSuperRegIterator SR(Reg, TRI);
SR.isValid() && RegNo < 0; ++SR)
RegNo = TRI->getDwarfRegNum(*SR, false);
assert(RegNo >= 0 && "Invalid Dwarf register number.");
return (unsigned short) RegNo;
}
/// Create a live-out register record for the given register Reg.
StackMaps::LiveOutReg
StackMaps::createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI,
const TargetRegisterInfo *TRI) const {
unsigned RegNo = getDwarfRegNum(Reg, MCRI, TRI);
unsigned Size = TRI->getMinimalPhysRegClass(Reg)->getSize();
unsigned LLVMRegNo = MCRI.getLLVMRegNum(RegNo, false);
unsigned SubRegIdx = MCRI.getSubRegIndex(LLVMRegNo, Reg);
unsigned Offset = 0;
if (SubRegIdx)
Offset = MCRI.getSubRegIdxOffset(SubRegIdx) / 8;
return LiveOutReg(Reg, RegNo, Offset + Size);
}
/// Parse the register live-out mask and return a vector of live-out registers
/// that need to be recorded in the stackmap.
StackMaps::LiveOutVec
StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
assert(Mask && "No register mask specified");
const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
MCContext &OutContext = AP.OutStreamer.getContext();
const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();
LiveOutVec LiveOuts;
for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
if ((Mask[Reg / 32] >> Reg % 32) & 1)
LiveOuts.push_back(createLiveOutReg(Reg, MCRI, TRI));
std::sort(LiveOuts.begin(), LiveOuts.end());
for (LiveOutVec::iterator I = LiveOuts.begin(), E = LiveOuts.end();
I != E; ++I) {
if (!I->Reg)
continue;
for (LiveOutVec::iterator II = next(I); II != E; ++II) {
if (I->RegNo != II->RegNo)
break;
I->Size = std::max(I->Size, II->Size);
if (TRI->isSuperRegister(I->Reg, II->Reg))
I->Reg = II->Reg;
II->Reg = 0;
}
}
LiveOuts.erase(std::remove_if(LiveOuts.begin(), LiveOuts.end(),
LiveOutReg::isInvalid), LiveOuts.end());
return LiveOuts;
}
void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE,
@ -192,8 +129,7 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
MCSymbol *MILabel = OutContext.CreateTempSymbol();
AP.OutStreamer.EmitLabel(MILabel);
LocationVec Locations;
LiveOutVec LiveOuts;
LocationVec CallsiteLocs;
if (recordResult) {
std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
@ -202,7 +138,7 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
Location &Loc = ParseResult.first;
assert(Loc.LocType == Location::Register &&
"Stackmap return location must be a register.");
Locations.push_back(Loc);
CallsiteLocs.push_back(Loc);
}
while (MOI != MOE) {
@ -215,9 +151,7 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
Loc.Offset = ConstPool.getConstantIndex(Loc.Offset);
}
// Skip the register mask and register live-out mask
if (Loc.LocType != Location::Unprocessed)
Locations.push_back(Loc);
CallsiteLocs.push_back(Loc);
}
const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
@ -225,23 +159,21 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
OutContext);
if (MOI->isRegLiveOut())
LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, Locations, LiveOuts));
CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, CallsiteLocs));
}
static MachineInstr::const_mop_iterator
getStackMapEndMOP(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) {
for (; MOI != MOE; ++MOI)
if (MOI->isRegLiveOut() || (MOI->isReg() && MOI->isImplicit()))
if (MOI->isRegMask() || (MOI->isReg() && MOI->isImplicit()))
break;
return MOI;
}
void StackMaps::recordStackMap(const MachineInstr &MI) {
assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
assert(MI.getOpcode() == TargetOpcode::STACKMAP && "exected stackmap");
int64_t ID = MI.getOperand(0).getImm();
recordStackMapOpers(MI, ID, llvm::next(MI.operands_begin(), 2),
@ -250,7 +182,7 @@ void StackMaps::recordStackMap(const MachineInstr &MI) {
}
void StackMaps::recordPatchPoint(const MachineInstr &MI) {
assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");
assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "exected stackmap");
PatchPointOpers opers(&MI);
int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm();
@ -289,11 +221,6 @@ void StackMaps::recordPatchPoint(const MachineInstr &MI) {
/// uint16 : Dwarf RegNum
/// int32 : Offset
/// }
/// uint16 : NumLiveOuts
/// LiveOuts[NumLiveOuts]
/// uint16 : Dwarf RegNum
/// uint8 : Reserved
/// uint8 : Size in Bytes
/// }
///
/// Location Encoding, Type, Value:
@ -346,7 +273,6 @@ void StackMaps::serializeToStackMapSection() {
uint64_t CallsiteID = CSII->ID;
const LocationVec &CSLocs = CSII->Locations;
const LiveOutVec &LiveOuts = CSII->LiveOuts;
DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n");
@ -354,12 +280,11 @@ void StackMaps::serializeToStackMapSection() {
// runtime than crash in case of in-process compilation. Currently, we do
// simple overflow checks, but we may eventually communicate other
// compilation errors this way.
if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
AP.OutStreamer.EmitIntValue(UINT64_MAX, 8); // Invalid ID.
if (CSLocs.size() > UINT16_MAX) {
AP.OutStreamer.EmitIntValue(UINT32_MAX, 8); // Invalid ID.
AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
AP.OutStreamer.EmitIntValue(0, 2); // Reserved.
AP.OutStreamer.EmitIntValue(0, 2); // 0 locations.
AP.OutStreamer.EmitIntValue(0, 2); // 0 live-out registers.
continue;
}
@ -436,24 +361,6 @@ void StackMaps::serializeToStackMapSection() {
AP.OutStreamer.EmitIntValue(RegNo, 2);
AP.OutStreamer.EmitIntValue(Offset, 4);
}
DEBUG(dbgs() << WSMP << " has " << LiveOuts.size()
<< " live-out registers\n");
AP.OutStreamer.EmitIntValue(LiveOuts.size(), 2);
operIdx = 0;
for (LiveOutVec::const_iterator LI = LiveOuts.begin(), LE = LiveOuts.end();
LI != LE; ++LI, ++operIdx) {
DEBUG(dbgs() << WSMP << " LO " << operIdx << ": "
<< MCRI.getName(LI->Reg)
<< " [encoding: .short " << LI->RegNo
<< ", .byte 0, .byte " << LI->Size << "]\n");
AP.OutStreamer.EmitIntValue(LI->RegNo, 2);
AP.OutStreamer.EmitIntValue(0, 1);
AP.OutStreamer.EmitIntValue(LI->Size, 1);
}
}
AP.OutStreamer.AddBlankLine();

View File

@ -1,85 +0,0 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -disable-fp-elim | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -disable-fp-elim -enable-stackmap-liveness| FileCheck -check-prefix=LIVE %s
;
; Note: Print verbose stackmaps using -debug-only=stackmaps.
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; CHECK-NEXT: .long 0
; Num LargeConstants
; CHECK-NEXT: .long 0
; Num Callsites
; CHECK-NEXT: .long 3
; CHECK-LABEL: .long L{{.*}}-_liveness
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; LIVE-LABEL: .long L{{.*}}-_liveness
; LIVE-NEXT: .short 0
; LIVE-NEXT: .short 0
; LIVE-NEXT: .short 2
; LIVE-NEXT: .short 7
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 8
; LIVE-NEXT: .short 19
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 16
; CHECK-LABEL: .long L{{.*}}-_liveness
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; LIVE-LABEL: .long L{{.*}}-_liveness
; LIVE-NEXT: .short 0
; LIVE-NEXT: .short 0
; LIVE-NEXT: .short 6
; LIVE-NEXT: .short 0
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 2
; LIVE-NEXT: .short 7
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 8
; LIVE-NEXT: .short 8
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 8
; LIVE-NEXT: .short 17
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 32
; LIVE-NEXT: .short 18
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 32
; LIVE-NEXT: .short 19
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 16
; CHECK-LABEL: .long L{{.*}}-_liveness
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; LIVE-LABEL: .long L{{.*}}-_liveness
; LIVE-NEXT: .short 0
; LIVE-NEXT: .short 0
; LIVE-NEXT: .short 2
; LIVE-NEXT: .short 7
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 8
; LIVE-NEXT: .short 19
; LIVE-NEXT: .byte 0
; LIVE-NEXT: .byte 16
define void @liveness() {
entry:
%a1 = call <2 x double> asm sideeffect "", "={xmm2}"() nounwind
call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 1, i32 5)
%a2 = call i64 asm sideeffect "", "={r8}"() nounwind
%a3 = call i8 asm sideeffect "", "={ah}"() nounwind
%a4 = call <4 x double> asm sideeffect "", "={ymm0}"() nounwind
%a5 = call <4 x double> asm sideeffect "", "={ymm1}"() nounwind
call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 2, i32 5)
call void asm sideeffect "", "{r8},{ah},{ymm0},{ymm1}"(i64 %a2, i8 %a3, <4 x double> %a4, <4 x double> %a5) nounwind
call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 5)
call void asm sideeffect "", "{xmm2}"(<2 x double> %a1) nounwind
ret void
}
declare void @llvm.experimental.stackmap(i64, i32, ...)

View File

@ -183,15 +183,15 @@ entry:
;
; Verify 17 stack map entries.
;
; CHECK-LABEL: .long L{{.*}}-_spilledValue
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 17
; CHECK-LABEL:.long L{{.*}}-_spilledValue
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 17
;
; Check that at least one is a spilled entry from RBP.
; Location: Indirect RBP + ...
; CHECK: .byte 3
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 6
; CHECK: .byte 3
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 6
define void @spilledValue(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16) {
entry:
call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 11, i32 15, i8* null, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16)
@ -202,15 +202,15 @@ entry:
;
; Verify 17 stack map entries.
;
; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 17
; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 17
;
; Check that at least one is a spilled entry from RBP.
; Location: Indirect RBP + ...
; CHECK: .byte 3
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 6
; CHECK: .byte 3
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 6
define webkit_jscc void @spilledStackMapValue(i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16) {
entry:
call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 12, i32 15, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16)
@ -219,16 +219,16 @@ entry:
; Spill a subregister stackmap operand.
;
; CHECK-LABEL: .long L{{.*}}-_spillSubReg
; CHECK-NEXT: .short 0
; CHECK-LABEL: .long L{{.*}}-_spillSubReg
; CHECK-NEXT: .short 0
; 4 locations
; CHECK-NEXT: .short 1
; CHECK-NEXT: .short 1
;
; Check that the subregister operand is a 4-byte spill.
; Location: Indirect, 4-byte, RBP + ...
; CHECK: .byte 3
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .short 6
; CHECK: .byte 3
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .short 6
define void @spillSubReg(i64 %arg) #0 {
bb:
br i1 undef, label %bb1, label %bb2
@ -259,23 +259,23 @@ bb61:
; Map a single byte subregister. There is no DWARF register number, so
; we expect the register to be encoded with the proper size and spill offset. We don't know which
;
; CHECK-LABEL: .long L{{.*}}-_subRegOffset
; CHECK-NEXT: .short 0
; CHECK-LABEL: .long L{{.*}}-_subRegOffset
; CHECK-NEXT: .short 0
; 2 locations
; CHECK-NEXT: .short 2
; CHECK-NEXT: .short 2
;
; Check that the subregister operands are 1-byte spills.
; Location 0: Register, 4-byte, AL
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
;
; Location 1: Register, 4-byte, BL
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .short 3
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .short 3
; CHECK-NEXT: .long 0
define void @subRegOffset(i16 %arg) {
%v = mul i16 %arg, 5
%a0 = trunc i16 %v to i8
@ -289,10 +289,10 @@ define void @subRegOffset(i16 %arg) {
; Map a constant value.
;
; CHECK-LABEL: .long L{{.*}}-_liveConstant
; CHECK-NEXT: .short 0
; CHECK-LABEL: .long L{{.*}}-_liveConstant
; CHECK-NEXT: .short 0
; 1 location
; CHECK-NEXT: .short 1
; CHECK-NEXT: .short 1
; Loc 0: SmallConstant
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 8
@ -316,9 +316,9 @@ define void @liveConstant() {
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 6
; CHECK-NEXT: .long
; CHECK-NEXT: .quad
; Callsite 17
; CHECK-LABEL: .long L{{.*}}-_directFrameIdx
; CHECK-NEXT: .long L{{.*}}-_directFrameIdx
; CHECK-NEXT: .short 0
; 2 locations
; CHECK-NEXT: .short 2