summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2013-11-17 01:36:23 +0000
committerAndrew Trick <atrick@apple.com>2013-11-17 01:36:23 +0000
commitbb756ca24401e190e3b704e5d92759c7a79cc6b7 (patch)
tree0c4bcba47b3a9717739a7c8f876a88363dc3ae02 /lib
parentb7dabccbce5fc6fcf7b36669eb04abcb001e7f9e (diff)
downloadllvm-bb756ca24401e190e3b704e5d92759c7a79cc6b7.tar.gz
llvm-bb756ca24401e190e3b704e5d92759c7a79cc6b7.tar.bz2
llvm-bb756ca24401e190e3b704e5d92759c7a79cc6b7.tar.xz
Added a size field to the stack map record to handle subregister spills.
Implementing this on bigendian platforms could get strange. I added a target hook, getStackSlotRange, per Jakob's recommendation to make this as explicit as possible. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194942 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/InlineSpiller.cpp5
-rw-r--r--lib/CodeGen/StackMaps.cpp20
-rw-r--r--lib/CodeGen/TargetInstrInfo.cpp31
-rw-r--r--lib/Target/X86/X86AsmPrinter.h3
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp13
-rw-r--r--lib/Target/X86/X86MCInstLower.cpp37
6 files changed, 91 insertions, 18 deletions
diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp
index 99d2bd46a2..bb0e642313 100644
--- a/lib/CodeGen/InlineSpiller.cpp
+++ b/lib/CodeGen/InlineSpiller.cpp
@@ -1057,6 +1057,9 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> > Ops,
bool WasCopy = MI->isCopy();
unsigned ImpReg = 0;
+ bool SpillSubRegs = (MI->getOpcode() == TargetOpcode::PATCHPOINT ||
+ MI->getOpcode() == TargetOpcode::STACKMAP);
+
// TargetInstrInfo::foldMemoryOperand only expects explicit, non-tied
// operands.
SmallVector<unsigned, 8> FoldOps;
@@ -1068,7 +1071,7 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> > Ops,
continue;
}
// FIXME: Teach targets to deal with subregs.
- if (MO.getSubReg())
+ if (!SpillSubRegs && MO.getSubReg())
return false;
// We cannot fold a load instruction into a def.
if (LoadMI && MO.isDef())
diff --git a/lib/CodeGen/StackMaps.cpp b/lib/CodeGen/StackMaps.cpp
index 89da78294f..0eeec83117 100644
--- a/lib/CodeGen/StackMaps.cpp
+++ b/lib/CodeGen/StackMaps.cpp
@@ -41,7 +41,7 @@ void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID,
if (recordResult) {
std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
- OpParser(MI.operands_begin(), llvm::next(MI.operands_begin(), 1));
+ OpParser(MI.operands_begin(), llvm::next(MI.operands_begin()), AP.TM);
Location &Loc = ParseResult.first;
assert(Loc.LocType == Location::Register &&
@@ -51,7 +51,7 @@ void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID,
while (MOI != MOE) {
std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
- OpParser(MOI, MOE);
+ OpParser(MOI, MOE, AP.TM);
Location &Loc = ParseResult.first;
@@ -86,7 +86,7 @@ void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID,
/// uint16 : NumLocations
/// Location[NumLocations] {
/// uint8 : Register | Direct | Indirect | Constant | ConstantIndex
-/// uint8 : Reserved (location flags)
+/// uint8 : Size in Bytes
/// uint16 : Dwarf RegNum
/// int32 : Offset
/// }
@@ -200,12 +200,22 @@ void StackMaps::serializeToStackMapSection() {
);
unsigned RegNo = 0;
+ int Offset = Loc.Offset;
if(Loc.Reg) {
RegNo = MCRI.getDwarfRegNum(Loc.Reg, false);
for (MCSuperRegIterator SR(Loc.Reg, TRI);
SR.isValid() && (int)RegNo < 0; ++SR) {
RegNo = TRI->getDwarfRegNum(*SR, false);
}
+ // If this is a register location, put the subregister byte offset in
+ // the location offset.
+ if (Loc.LocType == Location::Register) {
+ assert(!Loc.Offset && "Register location should have zero offset");
+ unsigned LLVMRegNo = MCRI.getLLVMRegNum(RegNo, false);
+ unsigned SubRegIdx = MCRI.getSubRegIndex(LLVMRegNo, Loc.Reg);
+ if (SubRegIdx)
+ Offset = MCRI.getSubRegIdxOffset(SubRegIdx);
+ }
}
else {
assert((Loc.LocType != Location::Register
@@ -213,9 +223,9 @@ void StackMaps::serializeToStackMapSection() {
"Missing location register");
}
AP.OutStreamer.EmitIntValue(Loc.LocType, 1);
- AP.OutStreamer.EmitIntValue(0, 1); // Reserved location flags.
+ AP.OutStreamer.EmitIntValue(Loc.Size, 1);
AP.OutStreamer.EmitIntValue(RegNo, 2);
- AP.OutStreamer.EmitIntValue(Loc.Offset, 4);
+ AP.OutStreamer.EmitIntValue(Offset, 4);
}
}
diff --git a/lib/CodeGen/TargetInstrInfo.cpp b/lib/CodeGen/TargetInstrInfo.cpp
index edeca3d5b8..bf4fd6587e 100644
--- a/lib/CodeGen/TargetInstrInfo.cpp
+++ b/lib/CodeGen/TargetInstrInfo.cpp
@@ -17,6 +17,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
+#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/Support/CommandLine.h"
@@ -276,6 +277,36 @@ bool TargetInstrInfo::hasStoreToStackSlot(const MachineInstr *MI,
return false;
}
+bool TargetInstrInfo::getStackSlotRange(const TargetRegisterClass *RC,
+ unsigned SubIdx, unsigned &Size,
+ unsigned &Offset,
+ const TargetMachine *TM) const {
+ if (!SubIdx) {
+ Size = RC->getSize();
+ Offset = 0;
+ return true;
+ }
+ unsigned BitSize = TM->getRegisterInfo()->getSubRegIdxSize(SubIdx);
+ // Convert bit size to byte size to be consistent with
+ // MCRegisterClass::getSize().
+ if (BitSize % 8)
+ return false;
+
+ int BitOffset = TM->getRegisterInfo()->getSubRegIdxOffset(SubIdx);
+ if (BitOffset < 0 || BitOffset % 8)
+ return false;
+
+ Size = BitSize /= 8;
+ Offset = (unsigned)BitOffset / 8;
+
+ assert(RC->getSize() >= (Offset + Size) && "bad subregister range");
+
+ if (!TM->getDataLayout()->isLittleEndian()) {
+ Offset = RC->getSize() - (Offset + Size);
+ }
+ return true;
+}
+
void TargetInstrInfo::reMaterialize(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg,
diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h
index 050c78df6a..24a768b933 100644
--- a/lib/Target/X86/X86AsmPrinter.h
+++ b/lib/Target/X86/X86AsmPrinter.h
@@ -34,7 +34,8 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
// This method is implemented in X86MCInstLower.cpp.
static std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
stackmapOperandParser(MachineInstr::const_mop_iterator MOI,
- MachineInstr::const_mop_iterator MOE);
+ MachineInstr::const_mop_iterator MOE,
+ const TargetMachine &TM);
public:
explicit X86AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 1a6d5ca829..b13fd33d4f 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -4239,9 +4239,20 @@ static MachineInstr* foldPatchpoint(MachineFunction &MF,
for (unsigned i = StartIdx; i < MI->getNumOperands(); ++i) {
MachineOperand &MO = MI->getOperand(i);
if (std::find(Ops.begin(), Ops.end(), i) != Ops.end()) {
+ assert(MO.getReg() && "patchpoint can only fold a vreg operand");
+ // Compute the spill slot size and offset.
+ const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(MO.getReg());
+ unsigned SpillSize;
+ unsigned SpillOffset;
+ bool Valid = TII.getStackSlotRange(RC, MO.getSubReg(), SpillSize,
+ SpillOffset, &MF.getTarget());
+ if (!Valid)
+ report_fatal_error("cannot spill patchpoint subregister operand");
+
MIB.addOperand(MachineOperand::CreateImm(StackMaps::IndirectMemRefOp));
+ MIB.addOperand(MachineOperand::CreateImm(SpillSize));
MIB.addOperand(MachineOperand::CreateFI(FrameIndex));
- addOffset(MIB, 0);
+ addOffset(MIB, SpillOffset);
}
else
MIB.addOperand(MO);
diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp
index 90033dd8f6..4e27ef0761 100644
--- a/lib/Target/X86/X86MCInstLower.cpp
+++ b/lib/Target/X86/X86MCInstLower.cpp
@@ -676,7 +676,7 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
}
static std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
-parseMemoryOperand(StackMaps::Location::LocationType LocTy,
+parseMemoryOperand(StackMaps::Location::LocationType LocTy, unsigned Size,
MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) {
@@ -701,12 +701,13 @@ parseMemoryOperand(StackMaps::Location::LocationType LocTy,
(void)ZeroReg;
return std::make_pair(
- Location(LocTy, Base.getReg(), Disp.getImm()), ++MOI);
+ Location(LocTy, Size, Base.getReg(), Disp.getImm()), ++MOI);
}
std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
X86AsmPrinter::stackmapOperandParser(MachineInstr::const_mop_iterator MOI,
- MachineInstr::const_mop_iterator MOE) {
+ MachineInstr::const_mop_iterator MOE,
+ const TargetMachine &TM) {
typedef StackMaps::Location Location;
@@ -717,26 +718,42 @@ X86AsmPrinter::stackmapOperandParser(MachineInstr::const_mop_iterator MOI,
if (MOP.isImm()) {
switch (MOP.getImm()) {
default: llvm_unreachable("Unrecognized operand type.");
- case StackMaps::DirectMemRefOp:
- return parseMemoryOperand(StackMaps::Location::Direct,
+ case StackMaps::DirectMemRefOp: {
+ unsigned Size = TM.getDataLayout()->getPointerSizeInBits();
+ assert((Size % 8) == 0 && "Need pointer size in bytes.");
+ Size /= 8;
+ return parseMemoryOperand(StackMaps::Location::Direct, Size,
llvm::next(MOI), MOE);
- case StackMaps::IndirectMemRefOp:
- return parseMemoryOperand(StackMaps::Location::Indirect,
+ }
+ case StackMaps::IndirectMemRefOp: {
+ ++MOI;
+ int64_t Size = MOI->getImm();
+ assert(Size > 0 && "Need a valid size for indirect memory locations.");
+ return parseMemoryOperand(StackMaps::Location::Indirect, Size,
llvm::next(MOI), MOE);
+ }
case StackMaps::ConstantOp: {
++MOI;
assert(MOI->isImm() && "Expected constant operand.");
int64_t Imm = MOI->getImm();
- return std::make_pair(Location(Location::Constant, 0, Imm), ++MOI);
+ return std::make_pair(
+ Location(Location::Constant, sizeof(int64_t), 0, Imm), ++MOI);
}
}
}
- // Otherwise this is a reg operand.
+ // 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
+ // track the actual size of the data type if it needs to.)
assert(MOP.isReg() && "Expected register operand here.");
assert(TargetRegisterInfo::isPhysicalRegister(MOP.getReg()) &&
"Virtreg operands should have been rewritten before now.");
- return std::make_pair(Location(Location::Register, MOP.getReg(), 0), ++MOI);
+ const TargetRegisterClass *RC =
+ TM.getRegisterInfo()->getMinimalPhysRegClass(MOP.getReg());
+ assert(!MOP.getSubReg() && "Physical subreg still around.");
+ return std::make_pair(
+ Location(Location::Register, RC->getSize(), MOP.getReg(), 0), ++MOI);
}
static MachineInstr::const_mop_iterator