[llvm] r194942 - Added a size field to the stack map record to handle subregister spills.

Andrew Trick atrick at apple.com
Sat Nov 16 17:36:24 PST 2013


Author: atrick
Date: Sat Nov 16 19:36:23 2013
New Revision: 194942

URL: http://llvm.org/viewvc/llvm-project?rev=194942&view=rev
Log:
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.

Modified:
    llvm/trunk/include/llvm/CodeGen/StackMaps.h
    llvm/trunk/include/llvm/Target/TargetInstrInfo.h
    llvm/trunk/lib/CodeGen/InlineSpiller.cpp
    llvm/trunk/lib/CodeGen/StackMaps.cpp
    llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp
    llvm/trunk/lib/Target/X86/X86AsmPrinter.h
    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
    llvm/trunk/lib/Target/X86/X86MCInstLower.cpp
    llvm/trunk/test/CodeGen/X86/anyregcc.ll
    llvm/trunk/test/CodeGen/X86/stackmap.ll

Modified: llvm/trunk/include/llvm/CodeGen/StackMaps.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMaps.h?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/StackMaps.h (original)
+++ llvm/trunk/include/llvm/CodeGen/StackMaps.h Sat Nov 16 19:36:23 2013
@@ -26,18 +26,19 @@ public:
     enum LocationType { Unprocessed, Register, Direct, Indirect, Constant,
                         ConstantIndex };
     LocationType LocType;
+    unsigned Size;
     unsigned Reg;
     int64_t Offset;
-    Location() : LocType(Unprocessed), Reg(0), Offset(0) {}
-    Location(LocationType LocType, unsigned Reg, int64_t Offset)
-      : LocType(LocType), Reg(Reg), Offset(Offset) {}
+    Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {}
+    Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset)
+      : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}
   };
 
   // Typedef a function pointer for functions that parse sequences of operands
   // and return a Location, plus a new "next" operand iterator.
   typedef std::pair<Location, MachineInstr::const_mop_iterator>
     (*OperandParser)(MachineInstr::const_mop_iterator,
-                     MachineInstr::const_mop_iterator);
+                     MachineInstr::const_mop_iterator, const TargetMachine&);
 
   // OpTypes are used to encode information about the following logical
   // operand (which may consist of several MachineOperands) for the

Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Sat Nov 16 19:36:23 2013
@@ -181,6 +181,23 @@ public:
     return false;
   }
 
+  /// Compute the size in bytes and offset within a stack slot of a spilled
+  /// register or subregister.
+  ///
+  /// \param [out] Size in bytes of the spilled value.
+  /// \param [out] Offset in bytes within the stack slot.
+  /// \returns true if both Size and Offset are successfully computed.
+  ///
+  /// Not all subregisters have computable spill slots. For example,
+  /// subregisters registers may not be byte-sized, and a pair of discontiguous
+  /// subregisters has no single offset.
+  ///
+  /// Targets with nontrivial bigendian implementations may need to override
+  /// this, particularly to support spilled vector registers.
+  virtual bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx,
+                                 unsigned &Size, unsigned &Offset,
+                                 const TargetMachine *TM) const;
+
   /// reMaterialize - Re-issue the specified 'original' instruction at the
   /// specific location targeting a new destination register.
   /// The register in Orig->getOperand(0).getReg() will be substituted by

Modified: llvm/trunk/lib/CodeGen/InlineSpiller.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/InlineSpiller.cpp?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/InlineSpiller.cpp (original)
+++ llvm/trunk/lib/CodeGen/InlineSpiller.cpp Sat Nov 16 19:36:23 2013
@@ -1057,6 +1057,9 @@ foldMemoryOperand(ArrayRef<std::pair<Mac
   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<Mac
       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())

Modified: llvm/trunk/lib/CodeGen/StackMaps.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMaps.cpp?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/StackMaps.cpp (original)
+++ llvm/trunk/lib/CodeGen/StackMaps.cpp Sat Nov 16 19:36:23 2013
@@ -41,7 +41,7 @@ void StackMaps::recordStackMap(const Mac
 
   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 Mac
 
   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 Mac
 ///   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::serializeToStackMapSecti
       );
 
       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::serializeToStackMapSecti
                "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);
     }
   }
 

Modified: llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp Sat Nov 16 19:36:23 2013
@@ -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::hasStoreToStackSlo
   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,

Modified: llvm/trunk/lib/Target/X86/X86AsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.h?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86AsmPrinter.h (original)
+++ llvm/trunk/lib/Target/X86/X86AsmPrinter.h Sat Nov 16 19:36:23 2013
@@ -34,7 +34,8 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrin
   // 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)

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Sat Nov 16 19:36:23 2013
@@ -4239,9 +4239,20 @@ static MachineInstr* foldPatchpoint(Mach
   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);

Modified: llvm/trunk/lib/Target/X86/X86MCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86MCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86MCInstLower.cpp Sat Nov 16 19:36:23 2013
@@ -676,7 +676,7 @@ static void LowerTlsAddr(MCStreamer &Out
 }
 
 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::
   (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(Mac
   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

Modified: llvm/trunk/test/CodeGen/X86/anyregcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/anyregcc.ll?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/anyregcc.ll (original)
+++ llvm/trunk/test/CodeGen/X86/anyregcc.ll Sat Nov 16 19:36:23 2013
@@ -18,17 +18,17 @@
 ; CHECK-NEXT:   .short  3
 ; Loc 0: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 4
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 1: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 4
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 2: Constant 3
 ; CHECK-NEXT:   .byte 4
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .long 3
 define i64 @test() nounwind ssp uwtable {
@@ -45,12 +45,12 @@ entry:
 ; CHECK-NEXT:   .short  2
 ; Loc 0: Register <-- this is the return register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 1: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 define i64 @property_access1(i8* %obj) nounwind ssp uwtable {
@@ -68,12 +68,12 @@ entry:
 ; CHECK-NEXT:   .short  2
 ; Loc 0: Register <-- this is the return register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 1: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 define i64 @property_access2() nounwind ssp uwtable {
@@ -92,12 +92,12 @@ entry:
 ; CHECK-NEXT:   .short  2
 ; Loc 0: Register <-- this is the return register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 1: Register <-- this will be folded once folding for FI is implemented
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 define i64 @property_access3() nounwind ssp uwtable {
@@ -116,72 +116,72 @@ entry:
 ; CHECK-NEXT:   .short  14
 ; Loc 0: Register <-- this is the return register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 1: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 2: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 3: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 4: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 5: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 6: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 7: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 8: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 9: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 10: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 11: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 12: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 13: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 define i64 @anyreg_test1(i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12, i8* %a13) nounwind ssp uwtable {
@@ -199,72 +199,72 @@ entry:
 ; CHECK-NEXT:   .short  14
 ; Loc 0: Register <-- this is the return register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 1: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 2: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 3: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 4: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 5: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 6: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 7: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 8: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 9: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 10: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 11: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 12: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 ; Loc 13: Register
 ; CHECK-NEXT:   .byte 1
-; CHECK-NEXT:   .byte 0
+; CHECK-NEXT:   .byte 8
 ; CHECK-NEXT:   .short {{[0-9]+}}
 ; CHECK-NEXT:   .long 0
 define i64 @anyreg_test2(i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12, i8* %a13) nounwind ssp uwtable {
@@ -284,17 +284,17 @@ entry:
 ; CHECK-NEXT: .short 3
 ; Loc 0: Register (some register that will be spilled to the stack)
 ; CHECK-NEXT: .byte  1
-; CHECK-NEXT: .byte  0
+; CHECK-NEXT: .byte  8
 ; CHECK-NEXT: .short {{[0-9]+}}
 ; CHECK-NEXT: .long  0
 ; Loc 1: Register RDI
 ; CHECK-NEXT: .byte  1
-; CHECK-NEXT: .byte  0
+; CHECK-NEXT: .byte  8
 ; CHECK-NEXT: .short 5
 ; CHECK-NEXT: .long  0
 ; Loc 1: Register RSI
 ; CHECK-NEXT: .byte  1
-; CHECK-NEXT: .byte  0
+; CHECK-NEXT: .byte  8
 ; CHECK-NEXT: .short 4
 ; CHECK-NEXT: .long  0
 define i64 @patchpoint_spilldef(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {

Modified: llvm/trunk/test/CodeGen/X86/stackmap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap.ll?rev=194942&r1=194941&r2=194942&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/stackmap.ll (original)
+++ llvm/trunk/test/CodeGen/X86/stackmap.ll Sat Nov 16 19:36:23 2013
@@ -9,7 +9,7 @@
 ; CHECK-NEXT:   .long   1
 ; CHECK-NEXT:   .quad   4294967296
 ; Num Callsites
-; CHECK-NEXT:   .long   9
+; CHECK-NEXT:   .long   11
 
 ; Constant arguments
 ;
@@ -19,22 +19,22 @@
 ; CHECK-NEXT:   .short  4
 ; SmallConstant
 ; CHECK-NEXT:   .byte   4
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .long   65535
 ; SmallConstant
 ; CHECK-NEXT:   .byte   4
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .long   65536
 ; SmallConstant
 ; CHECK-NEXT:   .byte   4
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  0
-; CHECK-NEXT:   .long   4294967295
+; CHECK-NEXT:   .long   -1
 ; LargeConstant at index 0
 ; CHECK-NEXT:   .byte   5
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .long   0
 
@@ -52,11 +52,11 @@ entry:
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .short  2
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long   0
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long  0
 define void @osrinline(i64 %a, i64 %b) {
@@ -77,11 +77,11 @@ entry:
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .short  2
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long   0
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long  0
 define void @osrcold(i64 %a, i64 %b) {
@@ -137,11 +137,11 @@ entry:
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .short  2
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long   0
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long   0
 define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
@@ -160,11 +160,11 @@ entry:
 ; CHECK-NEXT:   .short  0
 ; CHECK-NEXT:   .short  2
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long   0
 ; CHECK-NEXT:   .byte   1
-; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   8
 ; CHECK-NEXT:   .short  {{[0-9]+}}
 ; CHECK-NEXT:   .long   0
 define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
@@ -186,9 +186,9 @@ entry:
 ;
 ; Check that at least one is a spilled entry from RBP.
 ; Location: Indirect RBP + ...
-; CHECK: .byte 3
-; CHECK: .byte 0
-; CHECK: .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 (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 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)
@@ -206,15 +206,87 @@ entry:
 ;
 ; Check that at least one is a spilled entry from RBP.
 ; Location: Indirect RBP + ...
-; CHECK: .byte 3
-; CHECK: .byte 0
-; CHECK: .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 (i32, i32, ...)* @llvm.experimental.stackmap(i32 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)
   ret void
 }
 
+; Spill a subregister stackmap operand.
+;
+; CHECK:       .long 13
+; CHECK-LABEL: .long L{{.*}}-_spillSubReg
+; CHECK-NEXT:  .short 0
+; 4 locations
+; 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
+define void @spillSubReg(i64 %arg) #0 {
+bb:
+  br i1 undef, label %bb1, label %bb2
+
+bb1:
+  unreachable
+
+bb2:
+  %tmp = load i64* inttoptr (i64 140685446136880 to i64*)
+  br i1 undef, label %bb16, label %bb17
+
+bb16:
+  unreachable
+
+bb17:
+  %tmp32 = trunc i64 %tmp to i32
+  br i1 undef, label %bb60, label %bb61
+
+bb60:
+  tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
+  tail call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 13, i32 5, i32 %tmp32)
+  unreachable
+
+bb61:
+  unreachable
+}
+
+; 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:       .long 14
+; CHECK-LABEL: .long L{{.*}}-_subRegOffset
+; CHECK-NEXT:  .short 0
+; 2 locations
+; 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
+;
+; Location 1: Register, 4-byte, BL
+; 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
+  tail call void asm sideeffect "nop", "~{bx}"() nounwind
+  %arghi = lshr i16 %v, 8
+  %a1 = trunc i16 %arghi to i8
+  tail call void asm sideeffect "nop", "~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
+  tail call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 14, i32 5, i8 %a0, i8 %a1)
+  ret void
+}
+
 declare void @llvm.experimental.stackmap(i32, i32, ...)
 declare void @llvm.experimental.patchpoint.void(i32, i32, i8*, i32, ...)
 declare i64 @llvm.experimental.patchpoint.i64(i32, i32, i8*, i32, ...)





More information about the llvm-commits mailing list