<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Should be fixed in r197329.<div><br><div><div><div>On Dec 14, 2013, at 1:05 PM, Benjamin Kramer <<a href="mailto:benny.kra@gmail.com">benny.kra@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br>On 14.12.2013, at 07:53, Juergen Ributzka <<a href="mailto:juergen@apple.com">juergen@apple.com</a>> wrote:<br><br><blockquote type="cite">Author: ributzka<br>Date: Sat Dec 14 00:53:06 2013<br>New Revision: 197317<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=197317&view=rev">http://llvm.org/viewvc/llvm-project?rev=197317&view=rev</a><br>Log:<br>[Stackmap] Liveness Analysis Pass<br><br>This optional register liveness analysis pass can be enabled with either<br>-enable-stackmap-liveness, -enable-patchpoint-liveness, or both. The pass<br>traverses each basic block in a machine function. For each basic block the<br>instructions are processed in reversed order and if a patchpoint or stackmap<br>instruction is encountered the current live-out register set is encoded as a<br>register mask and attached to the instruction.<br><br>Later on during stackmap generation the live-out register mask is processed and<br>also emitted as part of the stackmap.<br><br>This information is optional and intended for optimization purposes only. This<br>will enable a client of the stackmap to reason about the registers it can use<br>and which registers need to be preserved.<br><br>Reviewed by Andy<br><br>Added:<br>  llvm/trunk/include/llvm/CodeGen/StackMapLivenessAnalysis.h<br>  llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp<br>  llvm/trunk/test/CodeGen/X86/stackmap-liveness.ll<br>Modified:<br>  llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h<br>  llvm/trunk/include/llvm/CodeGen/MachineFunction.h<br>  llvm/trunk/include/llvm/CodeGen/MachineOperand.h<br>  llvm/trunk/include/llvm/CodeGen/Passes.h<br>  llvm/trunk/include/llvm/CodeGen/StackMaps.h<br>  llvm/trunk/include/llvm/InitializePasses.h<br>  llvm/trunk/lib/CodeGen/CMakeLists.txt<br>  llvm/trunk/lib/CodeGen/CodeGen.cpp<br>  llvm/trunk/lib/CodeGen/MachineInstr.cpp<br>  llvm/trunk/lib/CodeGen/Passes.cpp<br>  llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>  llvm/trunk/lib/CodeGen/StackMaps.cpp<br>  llvm/trunk/test/CodeGen/X86/stackmap.ll<br><br>Modified: llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h (original)<br>+++ llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h Sat Dec 14 00:53:06 2013<br>@@ -145,6 +145,14 @@ class MachineFrameInfo {<br> /// to builtin \@llvm.returnaddress.<br> bool ReturnAddressTaken;<br><br>+  /// HasStackMap - This boolean keeps track of whether there is a call<br>+  /// to builtin \@llvm.experimental.stackmap.<br>+  bool HasStackMap;<br>+<br>+  /// HasPatchPoint - This boolean keeps track of whether there is a call<br>+  /// to builtin \@llvm.experimental.patchpoint.<br>+  bool HasPatchPoint;<br>+<br> /// StackSize - The prolog/epilog code inserter calculates the final stack<br> /// offsets for all of the fixed size objects, updating the Objects list<br> /// above.  It then updates StackSize to contain the number of bytes that need<br>@@ -235,6 +243,8 @@ public:<br>   HasVarSizedObjects = false;<br>   FrameAddressTaken = false;<br>   ReturnAddressTaken = false;<br>+    HasStackMap = false;<br>+    HasPatchPoint = false;<br>   AdjustsStack = false;<br>   HasCalls = false;<br>   StackProtectorIdx = -1;<br>@@ -280,6 +290,18 @@ public:<br> bool isReturnAddressTaken() const { return ReturnAddressTaken; }<br> void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; }<br><br>+  /// hasStackMap - This method may be called any time after instruction<br>+  /// selection is complete to determine if there is a call to builtin<br>+  /// \@llvm.experimental.stackmap.<br>+  bool hasStackMap() const { return HasStackMap; }<br>+  void setHasStackMap(bool s = true) { HasStackMap = s; }<br>+<br>+  /// hasPatchPoint - This method may be called any time after instruction<br>+  /// selection is complete to determine if there is a call to builtin<br>+  /// \@llvm.experimental.patchpoint.<br>+  bool hasPatchPoint() const { return HasPatchPoint; }<br>+  void setHasPatchPoint(bool s = true) { HasPatchPoint = s; }<br>+<br> /// getObjectIndexBegin - Return the minimum frame object index.<br> ///<br> int getObjectIndexBegin() const { return -NumFixedObjects; }<br><br>Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/CodeGen/MachineFunction.h (original)<br>+++ llvm/trunk/include/llvm/CodeGen/MachineFunction.h Sat Dec 14 00:53:06 2013<br>@@ -426,6 +426,15 @@ public:<br>   OperandRecycler.deallocate(Cap, Array);<br> }<br><br>+  /// \brief Allocate and initialize a register mask with @p NumRegister bits.<br>+  uint32_t *allocateRegisterMask(unsigned NumRegister) {<br>+    unsigned Size = (NumRegister + 31) / 32;<br>+    uint32_t *Mask = Allocator.Allocate<uint32_t>(Size);<br>+    for (unsigned i = 0; i != Size; ++i)<br>+      Mask[i] = 0;<br>+    return Mask;<br>+  }<br>+<br> /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand<br> /// pointers.  This array is owned by the MachineFunction.<br> MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num);<br><br>Modified: llvm/trunk/include/llvm/CodeGen/MachineOperand.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineOperand.h?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineOperand.h?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/CodeGen/MachineOperand.h (original)<br>+++ llvm/trunk/include/llvm/CodeGen/MachineOperand.h Sat Dec 14 00:53:06 2013<br>@@ -56,6 +56,7 @@ public:<br>   MO_GlobalAddress,          ///< Address of a global value<br>   MO_BlockAddress,           ///< Address of a basic block<br>   MO_RegisterMask,           ///< Mask of preserved registers.<br>+    MO_RegisterLiveOut,        ///< Mask of live-out registers.<br>   MO_Metadata,               ///< Metadata reference (for debug info)<br>   MO_MCSymbol                ///< MCSymbol reference (for debug/eh info)<br> };<br>@@ -153,7 +154,7 @@ private:<br>   const ConstantFP *CFP;    // For MO_FPImmediate.<br>   const ConstantInt *CI;    // For MO_CImmediate. Integers > 64bit.<br>   int64_t ImmVal;           // For MO_Immediate.<br>-    const uint32_t *RegMask;  // For MO_RegisterMask.<br>+    const uint32_t *RegMask;  // For MO_RegisterMask and MO_RegisterLiveOut.<br>   const MDNode *MD;         // For MO_Metadata.<br>   MCSymbol *Sym;            // For MO_MCSymbol<br><br>@@ -246,6 +247,8 @@ public:<br> bool isBlockAddress() const { return OpKind == MO_BlockAddress; }<br> /// isRegMask - Tests if this is a MO_RegisterMask operand.<br> bool isRegMask() const { return OpKind == MO_RegisterMask; }<br>+  /// isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.<br>+  bool isRegLiveOut() const { return OpKind == MO_RegisterLiveOut; }<br> /// isMetadata - Tests if this is a MO_Metadata operand.<br> bool isMetadata() const { return OpKind == MO_Metadata; }<br> bool isMCSymbol() const { return OpKind == MO_MCSymbol; }<br>@@ -476,6 +479,12 @@ public:<br>   return Contents.RegMask;<br> }<br><br>+  /// getRegLiveOut - Returns a bit mask of live-out registers.<br>+  const uint32_t *getRegLiveOut() const {<br>+    assert(isRegLiveOut() && "Wrong MachineOperand accessor");<br>+    return Contents.RegMask;<br>+  }<br>+<br> const MDNode *getMetadata() const {<br>   assert(isMetadata() && "Wrong MachineOperand accessor");<br>   return Contents.MD;<br>@@ -659,6 +668,12 @@ public:<br>   Op.Contents.RegMask = Mask;<br>   return Op;<br> }<br>+  static MachineOperand CreateRegLiveOut(const uint32_t *Mask) {<br>+    assert(Mask && "Missing live-out register mask");<br>+    MachineOperand Op(MachineOperand::MO_RegisterLiveOut);<br>+    Op.Contents.RegMask = Mask;<br>+    return Op;<br>+  }<br> static MachineOperand CreateMetadata(const MDNode *Meta) {<br>   MachineOperand Op(MachineOperand::MO_Metadata);<br>   Op.Contents.MD = Meta;<br><br>Modified: llvm/trunk/include/llvm/CodeGen/Passes.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/CodeGen/Passes.h (original)<br>+++ llvm/trunk/include/llvm/CodeGen/Passes.h Sat Dec 14 00:53:06 2013<br>@@ -568,6 +568,11 @@ namespace llvm {<br> /// bundles (created earlier, e.g. during pre-RA scheduling).<br> extern char &FinalizeMachineBundlesID;<br><br>+  /// StackMapLiveness - This pass analyses the register live-out set of<br>+  /// stackmap/patchpoint intrinsics and attaches the calculated information to<br>+  /// the intrinsic for later emission to the StackMap.<br>+  extern char &StackMapLivenessID;<br>+<br>} // End llvm namespace<br><br>#endif<br><br>Added: llvm/trunk/include/llvm/CodeGen/StackMapLivenessAnalysis.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMapLivenessAnalysis.h?rev=197317&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMapLivenessAnalysis.h?rev=197317&view=auto</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/CodeGen/StackMapLivenessAnalysis.h (added)<br>+++ llvm/trunk/include/llvm/CodeGen/StackMapLivenessAnalysis.h Sat Dec 14 00:53:06 2013<br>@@ -0,0 +1,65 @@<br>+//===--- StackMapLivenessAnalysis - StackMap Liveness Analysis --*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This pass calculates the liveness for each basic block in a function and<br>+// attaches the register live-out information to a stackmap or patchpoint<br>+// intrinsic if present.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H<br>+#define LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H<br>+<br>+#include "llvm/CodeGen/LivePhysRegs.h"<br>+#include "llvm/CodeGen/MachineFunctionPass.h"<br>+<br>+<br>+namespace llvm {<br>+<br>+/// \brief This pass calculates the liveness information for each basic block in<br>+/// a function and attaches the register live-out information to a stackmap or<br>+/// patchpoint intrinsic if present.<br>+///<br>+/// This is an optional pass that has to be explicitly enabled via the<br>+/// -enable-stackmap-liveness and/or -enable-patchpoint-liveness flag. The pass<br>+/// skips functions that don't have any stackmap or patchpoint intrinsics. The<br>+/// information provided by this pass is optional and not required by the<br>+/// aformentioned intrinsics to function.<br>+class StackMapLiveness : public MachineFunctionPass {<br>+  MachineFunction *MF;<br>+  const TargetRegisterInfo *TRI;<br>+  LivePhysRegs LiveRegs;<br>+public:<br>+  static char ID;<br>+<br>+  /// \brief Default construct and initialize the pass.<br>+  StackMapLiveness();<br>+<br>+  /// \brief Tell the pass manager which passes we depend on and what<br>+  /// information we preserve.<br>+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;<br>+<br>+  /// \brief Calculate the liveness information for the given machine function.<br>+  virtual bool runOnMachineFunction(MachineFunction &MF);<br>+<br>+private:<br>+  /// \brief Performs the actual liveness calculation for the function.<br>+  bool calculateLiveness();<br>+<br>+  /// \brief Add the current register live set to the instruction.<br>+  void addLiveOutSetToMI(MachineInstr &MI);<br>+<br>+  /// \brief Create a register mask and initialize it with the registers from<br>+  /// the register live set.<br>+  uint32_t *createRegisterMask() const;<br>+};<br>+<br>+} // llvm namespace<br>+<br>+#endif // LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H<br><br>Modified: llvm/trunk/include/llvm/CodeGen/StackMaps.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMaps.h?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMaps.h?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/CodeGen/StackMaps.h (original)<br>+++ llvm/trunk/include/llvm/CodeGen/StackMaps.h Sat Dec 14 00:53:06 2013<br>@@ -93,6 +93,22 @@ public:<br>     : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}<br> };<br><br>+  struct LiveOutReg {<br>+    unsigned short Reg;<br>+    unsigned short RegNo;<br>+    unsigned short Size;<br>+<br>+    LiveOutReg() : Reg(0), RegNo(0), Size(0) {}<br>+    LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size)<br>+      : Reg(Reg), RegNo(RegNo), Size(Size) {}<br>+<br>+    void MarkInvalid() { Reg = 0; }<br>+<br>+    // Only sort by the dwarf register number.<br>+    bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; }<br>+    static bool IsInvalid(const LiveOutReg &LO) { return LO.Reg == 0; }<br>+  };<br>+<br> // OpTypes are used to encode information about the following logical<br> // operand (which may consist of several MachineOperands) for the<br> // OpParser.<br>@@ -115,15 +131,18 @@ public:<br><br>private:<br> typedef SmallVector<Location, 8> LocationVec;<br>+  typedef SmallVector<LiveOutReg, 8> LiveOutVec;<br><br> struct CallsiteInfo {<br>   const MCExpr *CSOffsetExpr;<br>   uint64_t ID;<br>   LocationVec Locations;<br>+    LiveOutVec LiveOuts;<br>   CallsiteInfo() : CSOffsetExpr(0), ID(0) {}<br>   CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,<br>-                 LocationVec Locations)<br>-      : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {}<br>+                 LocationVec &Locations, LiveOutVec &LiveOuts)<br>+      : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations),<br>+        LiveOuts(LiveOuts) {}<br> };<br><br> typedef std::vector<CallsiteInfo> CallsiteInfoList;<br>@@ -154,8 +173,15 @@ private:<br><br> std::pair<Location, MachineInstr::const_mop_iterator><br> parseOperand(MachineInstr::const_mop_iterator MOI,<br>-               MachineInstr::const_mop_iterator MOE);<br>+               MachineInstr::const_mop_iterator MOE) const;<br><br>+  /// \brief Create a live-out register record for the given register @p Reg.<br>+  LiveOutReg createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI,<br>+                              const TargetRegisterInfo *TRI) const;<br>+<br>+  /// \brief Parse the register live-out mask and return a vector of live-out<br>+  /// registers that need to be recorded in the stackmap.<br>+  LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;<br><br> /// This should be called by the MC lowering code _immediately_ before<br> /// lowering the MI to an MCInst. It records where the operands for the<br><br>Modified: llvm/trunk/include/llvm/InitializePasses.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/InitializePasses.h (original)<br>+++ llvm/trunk/include/llvm/InitializePasses.h Sat Dec 14 00:53:06 2013<br>@@ -266,6 +266,7 @@ void initializeLoopVectorizePass(PassReg<br>void initializeSLPVectorizerPass(PassRegistry&);<br>void initializeBBVectorizePass(PassRegistry&);<br>void initializeMachineFunctionPrinterPassPass(PassRegistry&);<br>+void initializeStackMapLivenessPass(PassRegistry&);<br>}<br><br>#endif<br><br>Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)<br>+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Sat Dec 14 00:53:06 2013<br>@@ -97,6 +97,7 @@ add_llvm_library(LLVMCodeGen<br> StackColoring.cpp<br> StackProtector.cpp<br> StackSlotColoring.cpp<br>+  StackMapLivenessAnalysis.cpp<br> StackMaps.cpp<br> TailDuplication.cpp<br> TargetFrameLoweringImpl.cpp<br><br>Modified: llvm/trunk/lib/CodeGen/CodeGen.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/CodeGen.cpp (original)<br>+++ llvm/trunk/lib/CodeGen/CodeGen.cpp Sat Dec 14 00:53:06 2013<br>@@ -69,6 +69,7 @@ void llvm::initializeCodeGen(PassRegistr<br> initializeVirtRegRewriterPass(Registry);<br> initializeLowerIntrinsicsPass(Registry);<br> initializeMachineFunctionPrinterPassPass(Registry);<br>+  initializeStackMapLivenessPass(Registry);<br>}<br><br>void LLVMInitializeCodeGen(LLVMPassRegistryRef R) {<br><br>Modified: llvm/trunk/lib/CodeGen/MachineInstr.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineInstr.cpp?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineInstr.cpp?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/MachineInstr.cpp (original)<br>+++ llvm/trunk/lib/CodeGen/MachineInstr.cpp Sat Dec 14 00:53:06 2013<br>@@ -199,7 +199,8 @@ bool MachineOperand::isIdenticalTo(const<br> case MachineOperand::MO_BlockAddress:<br>   return getBlockAddress() == Other.getBlockAddress() &&<br>          getOffset() == Other.getOffset();<br>-  case MO_RegisterMask:<br>+  case MachineOperand::MO_RegisterMask:<br>+  case MachineOperand::MO_RegisterLiveOut:<br>   return getRegMask() == Other.getRegMask();<br> case MachineOperand::MO_MCSymbol:<br>   return getMCSymbol() == Other.getMCSymbol();<br>@@ -241,6 +242,7 @@ hash_code llvm::hash_value(const Machine<br>   return hash_combine(MO.getType(), MO.getTargetFlags(),<br>                       MO.getBlockAddress(), MO.getOffset());<br> case MachineOperand::MO_RegisterMask:<br>+  case MachineOperand::MO_RegisterLiveOut:<br>   return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask());<br> case MachineOperand::MO_Metadata:<br>   return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata());<br>@@ -368,6 +370,9 @@ void MachineOperand::print(raw_ostream &<br> case MachineOperand::MO_RegisterMask:<br>   OS << "<regmask>";<br>   break;<br>+  case MachineOperand::MO_RegisterLiveOut:<br>+    OS << "<regliveout>";<br>+    break;<br> case MachineOperand::MO_Metadata:<br>   OS << '<';<br>   WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);<br><br>Modified: llvm/trunk/lib/CodeGen/Passes.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Passes.cpp?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Passes.cpp?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/Passes.cpp (original)<br>+++ llvm/trunk/lib/CodeGen/Passes.cpp Sat Dec 14 00:53:06 2013<br>@@ -30,6 +30,11 @@<br><br>using namespace llvm;<br><br>+namespace llvm {<br>+extern cl::opt<bool> EnableStackMapLiveness;<br>+extern cl::opt<bool> EnablePatchPointLiveness;<br>+}<br>+<br>static cl::opt<bool> DisablePostRA("disable-post-ra", cl::Hidden,<br>   cl::desc("Disable Post Regalloc"));<br>static cl::opt<bool> DisableBranchFold("disable-branch-fold", cl::Hidden,<br>@@ -536,6 +541,9 @@ void TargetPassConfig::addMachinePasses(<br><br> if (addPreEmitPass())<br>   printAndVerify("After PreEmit passes");<br>+<br>+  if (EnableStackMapLiveness || EnablePatchPointLiveness)<br>+    addPass(&StackMapLivenessID);<br>}<br><br>/// Add passes that optimize machine instructions in SSA form.<br><br>Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)<br>+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Sat Dec 14 00:53:06 2013<br>@@ -6886,6 +6886,9 @@ void SelectionDAGBuilder::visitStackmap(<br> DAG.ReplaceAllUsesWith(Call, MN);<br><br> DAG.DeleteNode(Call);<br>+<br>+  // Inform the Frame Information that we have a stackmap in this function.<br>+  FuncInfo.MF->getFrameInfo()->setHasStackMap();<br>}<br><br>/// \brief Lower llvm.experimental.patchpoint directly to its target opcode.<br>@@ -7025,6 +7028,9 @@ void SelectionDAGBuilder::visitPatchpoin<br> } else<br>   DAG.ReplaceAllUsesWith(Call, MN);<br> DAG.DeleteNode(Call);<br>+<br>+  // Inform the Frame Information that we have a patchpoint in this function.<br>+  FuncInfo.MF->getFrameInfo()->setHasPatchPoint();<br>}<br><br>/// TargetLowering::LowerCallTo - This is the default LowerCallTo<br><br>Added: llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp?rev=197317&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp?rev=197317&view=auto</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp (added)<br>+++ llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp Sat Dec 14 00:53:06 2013<br>@@ -0,0 +1,128 @@<br>+//===-- StackMapLivenessAnalysis.cpp - StackMap live Out Analysis ----------===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file implements the StackMap Liveness analysis pass. The pass calculates<br>+// the liveness for each basic block in a function and attaches the register<br>+// live-out information to a stackmap or patchpoint intrinsic if present.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#define DEBUG_TYPE "stackmaps"<br>+#include "llvm/ADT/Statistic.h"<br>+#include "llvm/CodeGen/MachineFrameInfo.h"<br>+#include "llvm/CodeGen/MachineFunction.h"<br>+#include "llvm/CodeGen/MachineFunctionAnalysis.h"<br>+#include "llvm/CodeGen/Passes.h"<br>+#include "llvm/CodeGen/StackMapLivenessAnalysis.h"<br>+#include "llvm/Support/CommandLine.h"<br>+#include "llvm/Support/Debug.h"<br>+<br>+<br>+using namespace llvm;<br>+<br>+namespace llvm {<br>+cl::opt<bool> EnableStackMapLiveness("enable-stackmap-liveness",<br>+  cl::Hidden, cl::desc("Enable StackMap Liveness Analysis Pass"));<br>+cl::opt<bool> EnablePatchPointLiveness("enable-patchpoint-liveness",<br>+  cl::Hidden, cl::desc("Enable PatchPoint Liveness Analysis Pass"));<br>+}<br>+<br>+STATISTIC(NumStackMapFuncVisited, "Number of functions visited");<br>+STATISTIC(NumStackMapFuncSkipped, "Number of functions skipped");<br>+STATISTIC(NumBBsVisited,          "Number of basic blocks visited");<br>+STATISTIC(NumBBsHaveNoStackmap,   "Number of basic blocks with no stackmap");<br>+STATISTIC(NumStackMaps,           "Number of StackMaps visited");<br>+<br>+char StackMapLiveness::ID = 0;<br>+char &llvm::StackMapLivenessID = StackMapLiveness::ID;<br>+INITIALIZE_PASS(StackMapLiveness, "stackmap-liveness",<br>+                "StackMap Liveness Analysis", false, false)<br>+<br>+/// Default construct and initialize the pass.<br>+StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) {<br>+  initializeStackMapLivenessPass(*PassRegistry::getPassRegistry());<br>+}<br>+<br>+/// Tell the pass manager which passes we depend on and what information we<br>+/// preserve.<br>+void StackMapLiveness::getAnalysisUsage(AnalysisUsage &AU) const {<br>+  // We preserve all information.<br>+  AU.setPreservesAll();<br>+  AU.setPreservesCFG();<br>+  // Default dependencie for all MachineFunction passes.<br>+  AU.addRequired<MachineFunctionAnalysis>();<br>+}<br>+<br>+/// Calculate the liveness information for the given machine function.<br>+bool StackMapLiveness::runOnMachineFunction(MachineFunction &_MF) {<br>+  DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: "<br>+               << _MF.getName() << " **********\n");<br>+  MF = &_MF;<br>+  TRI = MF->getTarget().getRegisterInfo();<br>+  ++NumStackMapFuncVisited;<br>+<br>+  // Skip this function if there are no stackmaps or patchpoints to process.<br>+  if (!((MF->getFrameInfo()->hasStackMap() && EnableStackMapLiveness) ||<br>+        (MF->getFrameInfo()->hasPatchPoint() && EnablePatchPointLiveness))) {<br>+    ++NumStackMapFuncSkipped;<br>+    return false;<br>+  }<br>+  return calculateLiveness();<br>+}<br>+<br>+/// Performs the actual liveness calculation for the function.<br>+bool StackMapLiveness::calculateLiveness() {<br>+  bool HasChanged = false;<br>+  // For all basic blocks in the function.<br>+  for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end();<br>+       MBBI != MBBE; ++MBBI) {<br>+    DEBUG(dbgs() << "****** BB " << MBBI->getName() << " ******\n");<br>+    LiveRegs.init(TRI);<br>+    LiveRegs.addLiveOuts(MBBI);<br>+    bool HasStackMap = false;<br>+    // Reverse iterate over all instructions and add the current live register<br>+    // set to an instruction if we encounter a stackmap or patchpoint<br>+    // instruction.<br>+    for (MachineBasicBlock::reverse_iterator I = MBBI->rbegin(),<br>+         E = MBBI->rend(); I != E; ++I) {<br>+      int Opc = I->getOpcode();<br>+      if ((EnableStackMapLiveness && (Opc == TargetOpcode::STACKMAP)) ||<br>+          (EnablePatchPointLiveness && (Opc == TargetOpcode::PATCHPOINT))) {<br>+        addLiveOutSetToMI(*I);<br>+        HasChanged = true;<br>+        HasStackMap = true;<br>+        ++NumStackMaps;<br>+      }<br>+      DEBUG(dbgs() << "   " << *I << "   " << LiveRegs);<br>+      LiveRegs.stepBackward(*I);<br>+    }<br>+    ++NumBBsVisited;<br>+    if (!HasStackMap)<br>+      ++NumBBsHaveNoStackmap;<br>+  }<br>+  return HasChanged;<br>+}<br>+<br>+/// Add the current register live set to the instruction.<br>+void StackMapLiveness::addLiveOutSetToMI(MachineInstr &MI) {<br>+  uint32_t *Mask = createRegisterMask();<br>+  MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask);<br>+  MI.addOperand(*MF, MO);<br>+}<br>+<br>+/// Create a register mask and initialize it with the registers from the<br>+/// register live set.<br>+uint32_t *StackMapLiveness::createRegisterMask() const {<br>+  // The mask is owned and cleaned up by the Machine Function.<br>+  uint32_t *Mask = MF->allocateRegisterMask(TRI->getNumRegs());<br>+  for (LivePhysRegs::const_iterator RI = LiveRegs.begin(), RE = LiveRegs.end();<br>+       RI != RE; ++RI)<br>+    Mask[*RI / 32] |= 1U << (*RI % 32);<br>+  return Mask;<br>+}<br><br>Modified: llvm/trunk/lib/CodeGen/StackMaps.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMaps.cpp?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMaps.cpp?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/CodeGen/StackMaps.cpp (original)<br>+++ llvm/trunk/lib/CodeGen/StackMaps.cpp Sat Dec 14 00:53:06 2013<br>@@ -68,10 +68,10 @@ unsigned PatchPointOpers::getNextScratch<br><br>std::pair<StackMaps::Location, MachineInstr::const_mop_iterator><br>StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,<br>-                        MachineInstr::const_mop_iterator MOE) {<br>+                        MachineInstr::const_mop_iterator MOE) const {<br> const MachineOperand &MOP = *MOI;<br>-  assert(!MOP.isRegMask() && (!MOP.isReg() || !MOP.isImplicit()) &&<br>-         "Register mask and implicit operands should not be processed.");<br>+  assert((!MOP.isReg() || !MOP.isImplicit()) &&<br>+         "Implicit operands should not be processed.");<br><br> if (MOP.isImm()) {<br>   // Verify anyregcc<br>@@ -106,6 +106,9 @@ StackMaps::parseOperand(MachineInstr::co<br>   }<br> }<br><br>+  if (MOP.isRegMask() || MOP.isRegLiveOut())<br>+    return std::make_pair(Location(), ++MOI);<br>+<br> // Otherwise this is a reg operand. The physical register number will<br> // ultimately be encoded as a DWARF regno. The stack map also records the size<br> // of a spill slot that can hold the register content. (The runtime can<br>@@ -120,6 +123,65 @@ StackMaps::parseOperand(MachineInstr::co<br>   Location(Location::Register, RC->getSize(), MOP.getReg(), 0), ++MOI);<br>}<br><br>+/// Go up the super-register chain until we hit a valid dwarf register number.<br>+static unsigned short getDwarfRegNum(unsigned Reg, const MCRegisterInfo &MCRI,<br>+                                     const TargetRegisterInfo *TRI) {<br>+  int RegNo = MCRI.getDwarfRegNum(Reg, false);<br>+  for (MCSuperRegIterator SR(Reg, TRI);<br>+       SR.isValid() && RegNo < 0; ++SR)<br>+    RegNo = TRI->getDwarfRegNum(*SR, false);<br>+<br>+  assert(RegNo >= 0 && "Invalid Dwarf register number.");<br>+  return (unsigned short) RegNo;<br>+}<br>+<br>+/// Create a live-out register record for the given register Reg.<br>+StackMaps::LiveOutReg<br>+StackMaps::createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI,<br>+                            const TargetRegisterInfo *TRI) const {<br>+  unsigned RegNo = getDwarfRegNum(Reg, MCRI, TRI);<br>+  unsigned Size = TRI->getMinimalPhysRegClass(Reg)->getSize();<br>+  return LiveOutReg(Reg, RegNo, Size);<br>+}<br>+<br>+/// Parse the register live-out mask and return a vector of live-out registers<br>+/// that need to be recorded in the stackmap.<br>+StackMaps::LiveOutVec<br>+StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {<br>+  assert(Mask && "No register mask specified");<br>+  const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();<br>+  MCContext &OutContext = AP.OutStreamer.getContext();<br>+  const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();<br>+  LiveOutVec LiveOuts;<br>+<br>+  // Create a LiveOutReg for each bit that is set in the register mask.<br>+  for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)<br>+    if ((Mask[Reg / 32] >> Reg % 32) & 1)<br>+      LiveOuts.push_back(createLiveOutReg(Reg, MCRI, TRI));<br>+<br>+  // We don't need to keep track of a register if its super-register is already<br>+  // in the list. Merge entries that refer to the same dwarf register and use<br>+  // the maximum size that needs to be spilled.<br>+  std::sort(LiveOuts.begin(), LiveOuts.end());<br>+  for (LiveOutVec::iterator I = LiveOuts.begin(), E = LiveOuts.end();<br>+       I != E; ++I) {<br>+    for (LiveOutVec::iterator II = next(I); II != E; ++II) {<br>+      if (I->RegNo != II->RegNo) {<br>+        // Skip all the now invalid entries.<br>+        I = --II;<br>+        break;<br>+      }<br>+      I->Size = std::max(I->Size, II->Size);<br>+      if (TRI->isSuperRegister(I->Reg, II->Reg))<br>+        I->Reg = II->Reg;<br>+      II->MarkInvalid();<br>+    }<br>+  }<br>+  LiveOuts.erase(std::remove_if(LiveOuts.begin(), LiveOuts.end(),<br>+                                LiveOutReg::IsInvalid), LiveOuts.end());<br>+  return LiveOuts;<br>+}<br>+<br>void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,<br>                                   MachineInstr::const_mop_iterator MOI,<br>                                   MachineInstr::const_mop_iterator MOE,<br>@@ -129,7 +191,8 @@ void StackMaps::recordStackMapOpers(cons<br> MCSymbol *MILabel = OutContext.CreateTempSymbol();<br> AP.OutStreamer.EmitLabel(MILabel);<br><br>-  LocationVec CallsiteLocs;<br>+  LocationVec Locations;<br>+  LiveOutVec LiveOuts;<br><br> if (recordResult) {<br>   std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =<br>@@ -138,7 +201,7 @@ void StackMaps::recordStackMapOpers(cons<br>   Location &Loc = ParseResult.first;<br>   assert(Loc.LocType == Location::Register &&<br>          "Stackmap return location must be a register.");<br>-    CallsiteLocs.push_back(Loc);<br>+    Locations.push_back(Loc);<br> }<br><br> while (MOI != MOE) {<br>@@ -151,7 +214,9 @@ void StackMaps::recordStackMapOpers(cons<br>     Loc.Offset = ConstPool.getConstantIndex(Loc.Offset);<br>   }<br><br>-    CallsiteLocs.push_back(Loc);<br>+    // Skip the register mask and register live-out mask<br>+    if (Loc.LocType != Location::Unprocessed)<br>+      Locations.push_back(Loc);<br> }<br><br> const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(<br>@@ -159,21 +224,23 @@ void StackMaps::recordStackMapOpers(cons<br>   MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),<br>   OutContext);<br><br>-  CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, CallsiteLocs));<br>+  if (MOI->isRegLiveOut())<br>+    LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());<br></blockquote><br>valgrind[1] complains that MOI points to uninitialized memory here. If you look at the code you can easily see that MOI points to the end (MOI == MOE) at this point, that can't be right.<br><br>[1]<span class="Apple-converted-space"> </span><a href="http://lab.llvm.org:8011/builders/llvm-x86_64-linux-vg_leak/builds/1430">http://lab.llvm.org:8011/builders/llvm-x86_64-linux-vg_leak/builds/1430</a><br><br>- Ben<br><br><blockquote type="cite">+<br>+  CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, Locations, LiveOuts));<br>}<br><br>static MachineInstr::const_mop_iterator<br>getStackMapEndMOP(MachineInstr::const_mop_iterator MOI,<br>                 MachineInstr::const_mop_iterator MOE) {<br> for (; MOI != MOE; ++MOI)<br>-    if (MOI->isRegMask() || (MOI->isReg() && MOI->isImplicit()))<br>+    if (MOI->isRegLiveOut() || (MOI->isReg() && MOI->isImplicit()))<br>     break;<br>-<br> return MOI;<br>}<br><br>void StackMaps::recordStackMap(const MachineInstr &MI) {<br>-  assert(MI.getOpcode() == TargetOpcode::STACKMAP && "exected stackmap");<br>+  assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");<br><br> int64_t ID = MI.getOperand(0).getImm();<br> recordStackMapOpers(MI, ID, llvm::next(MI.operands_begin(), 2),<br>@@ -182,7 +249,7 @@ void StackMaps::recordStackMap(const Mac<br>}<br><br>void StackMaps::recordPatchPoint(const MachineInstr &MI) {<br>-  assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "exected stackmap");<br>+  assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");<br><br> PatchPointOpers opers(&MI);<br> int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm();<br>@@ -221,6 +288,11 @@ void StackMaps::recordPatchPoint(const M<br>///     uint16 : Dwarf RegNum<br>///     int32  : Offset<br>///   }<br>+///   uint16 : NumLiveOuts<br>+///   LiveOuts[NumLiveOuts]<br>+///     uint16 : Dwarf RegNum<br>+///     uint8  : Reserved<br>+///     uint8  : Size in Bytes<br>/// }<br>///<br>/// Location Encoding, Type, Value:<br>@@ -273,6 +345,7 @@ void StackMaps::serializeToStackMapSecti<br><br>   uint64_t CallsiteID = CSII->ID;<br>   const LocationVec &CSLocs = CSII->Locations;<br>+    const LiveOutVec &LiveOuts = CSII->LiveOuts;<br><br>   DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n");<br><br>@@ -280,11 +353,12 @@ void StackMaps::serializeToStackMapSecti<br>   // runtime than crash in case of in-process compilation. Currently, we do<br>   // simple overflow checks, but we may eventually communicate other<br>   // compilation errors this way.<br>-    if (CSLocs.size() > UINT16_MAX) {<br>-      AP.OutStreamer.EmitIntValue(UINT32_MAX, 8); // Invalid ID.<br>+    if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {<br>+      AP.OutStreamer.EmitIntValue(UINT64_MAX, 8); // Invalid ID.<br>     AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);<br>     AP.OutStreamer.EmitIntValue(0, 2); // Reserved.<br>     AP.OutStreamer.EmitIntValue(0, 2); // 0 locations.<br>+      AP.OutStreamer.EmitIntValue(0, 2); // 0 live-out registers.<br>     continue;<br>   }<br><br>@@ -361,6 +435,24 @@ void StackMaps::serializeToStackMapSecti<br>     AP.OutStreamer.EmitIntValue(RegNo, 2);<br>     AP.OutStreamer.EmitIntValue(Offset, 4);<br>   }<br>+<br>+    DEBUG(dbgs() << WSMP << "  has " << LiveOuts.size()<br>+                 << " live-out registers\n");<br>+<br>+    AP.OutStreamer.EmitIntValue(LiveOuts.size(), 2);<br>+<br>+    operIdx = 0;<br>+    for (LiveOutVec::const_iterator LI = LiveOuts.begin(), LE = LiveOuts.end();<br>+         LI != LE; ++LI, ++operIdx) {<br>+      DEBUG(dbgs() << WSMP << "  LO " << operIdx << ": "<br>+                   << MCRI.getName(LI->Reg)<br>+                   << "     [encoding: .short " << LI->RegNo<br>+                   << ", .byte 0, .byte " << LI->Size << "]\n");<br>+<br>+      AP.OutStreamer.EmitIntValue(LI->RegNo, 2);<br>+      AP.OutStreamer.EmitIntValue(0, 1);<br>+      AP.OutStreamer.EmitIntValue(LI->Size, 1);<br>+    }<br> }<br><br> AP.OutStreamer.AddBlankLine();<br><br>Added: llvm/trunk/test/CodeGen/X86/stackmap-liveness.ll<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap-liveness.ll?rev=197317&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap-liveness.ll?rev=197317&view=auto</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/X86/stackmap-liveness.ll (added)<br>+++ llvm/trunk/test/CodeGen/X86/stackmap-liveness.ll Sat Dec 14 00:53:06 2013<br>@@ -0,0 +1,178 @@<br>+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -disable-fp-elim | FileCheck %s<br>+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -disable-fp-elim -enable-stackmap-liveness| FileCheck -check-prefix=STACK %s<br>+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -disable-fp-elim -enable-patchpoint-liveness| FileCheck -check-prefix=PATCH %s<br>+;<br>+; Note: Print verbose stackmaps using -debug-only=stackmaps.<br>+<br>+; CHECK-LABEL:  .section  __LLVM_STACKMAPS,__llvm_stackmaps<br>+; CHECK-NEXT:   __LLVM_StackMaps:<br>+; CHECK-NEXT:   .long   0<br>+; Num LargeConstants<br>+; CHECK-NEXT:   .long   0<br>+; Num Callsites<br>+; CHECK-NEXT:   .long   5<br>+define void @stackmap_liveness() {<br>+entry:<br>+  %a1 = call <2 x double> asm sideeffect "", "={xmm2}"() nounwind<br>+; StackMap 1 (no liveness information available)<br>+; CHECK-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; CHECK-NEXT:   .short  0<br>+; CHECK-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; CHECK-NEXT:   .short  0<br>+<br>+; StackMap 1 (stackmap liveness information enabled)<br>+; STACK-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; STACK-NEXT:   .short  0<br>+; STACK-NEXT:   .short  0<br>+; Num LiveOut Entries: 2<br>+; STACK-NEXT:   .short  2<br>+; LiveOut Entry 1: %RSP (8 bytes)<br>+; STACK-NEXT:   .short  7<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 8<br>+; LiveOut Entry 2: %YMM2 (16 bytes) --> %XMM2<br>+; STACK-NEXT:   .short  19<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 16<br>+<br>+; StackMap 1 (patchpoint liveness information enabled)<br>+; PATCH-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; PATCH-NEXT:   .short  0<br>+; PATCH-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; PATCH-NEXT:   .short  0<br>+  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 1, i32 5)<br>+  %a2 = call i64 asm sideeffect "", "={r8}"() nounwind<br>+  %a3 = call i8 asm sideeffect "", "={ah}"() nounwind<br>+  %a4 = call <4 x double> asm sideeffect "", "={ymm0}"() nounwind<br>+  %a5 = call <4 x double> asm sideeffect "", "={ymm1}"() nounwind<br>+<br>+; StackMap 2 (no liveness information available)<br>+; CHECK-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; CHECK-NEXT:   .short  0<br>+; CHECK-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; CHECK-NEXT:   .short  0<br>+<br>+; StackMap 2 (stackmap liveness information enabled)<br>+; STACK-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; STACK-NEXT:   .short  0<br>+; STACK-NEXT:   .short  0<br>+; Num LiveOut Entries: 6<br>+; STACK-NEXT:   .short  6<br>+; LiveOut Entry 2: %RAX (1 bytes) --> %AL or %AH<br>+; STACK-NEXT:   .short  0<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 1<br>+; LiveOut Entry 2: %RSP (8 bytes)<br>+; STACK-NEXT:   .short  7<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 8<br>+; LiveOut Entry 2: %R8 (8 bytes)<br>+; STACK-NEXT:   .short  8<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 8<br>+; LiveOut Entry 2: %YMM0 (32 bytes)<br>+; STACK-NEXT:   .short  17<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 32<br>+; LiveOut Entry 2: %YMM1 (32 bytes)<br>+; STACK-NEXT:   .short  18<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 32<br>+; LiveOut Entry 2: %YMM2 (16 bytes) --> %XMM2<br>+; STACK-NEXT:   .short  19<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 16<br>+<br>+; StackMap 2 (patchpoint liveness information enabled)<br>+; PATCH-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; PATCH-NEXT:   .short  0<br>+; PATCH-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; PATCH-NEXT:   .short  0<br>+  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 2, i32 5)<br>+  call void asm sideeffect "", "{r8},{ah},{ymm0},{ymm1}"(i64 %a2, i8 %a3, <4 x double> %a4, <4 x double> %a5) nounwind<br>+<br>+; StackMap 3 (no liveness information available)<br>+; CHECK-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; CHECK-NEXT:   .short  0<br>+; CHECK-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; CHECK-NEXT:   .short  0<br>+<br>+; StackMap 3 (stackmap liveness information enabled)<br>+; STACK-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; STACK-NEXT:   .short  0<br>+; STACK-NEXT:   .short  0<br>+; Num LiveOut Entries: 2<br>+; STACK-NEXT:   .short  2<br>+; LiveOut Entry 2: %RSP (8 bytes)<br>+; STACK-NEXT:   .short  7<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 8<br>+; LiveOut Entry 2: %YMM2 (16 bytes) --> %XMM2<br>+; STACK-NEXT:   .short  19<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 16<br>+<br>+; StackMap 3 (patchpoint liveness information enabled)<br>+; PATCH-LABEL:  .long L{{.*}}-_stackmap_liveness<br>+; PATCH-NEXT:   .short  0<br>+; PATCH-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; PATCH-NEXT:   .short  0<br>+  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 5)<br>+  call void asm sideeffect "", "{xmm2}"(<2 x double> %a1) nounwind<br>+  ret void<br>+}<br>+<br>+define void @mixed_liveness() {<br>+entry:<br>+  %a1 = call <2 x double> asm sideeffect "", "={xmm2}"() nounwind<br>+; StackMap 4 (stackmap liveness information enabled)<br>+; STACK-LABEL:  .long L{{.*}}-_mixed_liveness<br>+; STACK-NEXT:   .short  0<br>+; STACK-NEXT:   .short  0<br>+; Num LiveOut Entries: 1<br>+; STACK-NEXT:   .short  1<br>+; LiveOut Entry 1: %YMM2 (16 bytes) --> %XMM2<br>+; STACK-NEXT:   .short  19<br>+; STACK-NEXT:   .byte 0<br>+; STACK-NEXT:   .byte 16<br>+; StackMap 5 (stackmap liveness information enabled)<br>+; STACK-LABEL:  .long L{{.*}}-_mixed_liveness<br>+; STACK-NEXT:   .short  0<br>+; STACK-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; STACK-NEXT:   .short  0<br>+<br>+; StackMap 4 (patchpoint liveness information enabled)<br>+; PATCH-LABEL:  .long L{{.*}}-_mixed_liveness<br>+; PATCH-NEXT:   .short  0<br>+; PATCH-NEXT:   .short  0<br>+; Num LiveOut Entries: 0<br>+; PATCH-NEXT:   .short  0<br>+; StackMap 5 (patchpoint liveness information enabled)<br>+; PATCH-LABEL:  .long L{{.*}}-_mixed_liveness<br>+; PATCH-NEXT:   .short  0<br>+; PATCH-NEXT:   .short  0<br>+; Num LiveOut Entries: 2<br>+; PATCH-NEXT:   .short  2<br>+; LiveOut Entry 1: %RSP (8 bytes)<br>+; PATCH-NEXT:   .short  7<br>+; PATCH-NEXT:   .byte 0<br>+; PATCH-NEXT:   .byte 8<br>+; LiveOut Entry 1: %YMM2 (16 bytes) --> %XMM2<br>+; PATCH-NEXT:   .short  19<br>+; PATCH-NEXT:   .byte 0<br>+; PATCH-NEXT:   .byte 16<br>+  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 4, i32 5)<br>+  call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 5, i32 0, i8* null, i32 0)<br>+  call void asm sideeffect "", "{xmm2}"(<2 x double> %a1) nounwind<br>+  ret void<br>+}<br>+<br>+declare void @llvm.experimental.stackmap(i64, i32, ...)<br>+declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)<br><br>Modified: llvm/trunk/test/CodeGen/X86/stackmap.ll<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap.ll?rev=197317&r1=197316&r2=197317&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap.ll?rev=197317&r1=197316&r2=197317&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/X86/stackmap.ll (original)<br>+++ llvm/trunk/test/CodeGen/X86/stackmap.ll Sat Dec 14 00:53:06 2013<br>@@ -183,15 +183,15 @@ entry:<br>;<br>; Verify 17 stack map entries.<br>;<br>-; CHECK-LABEL:.long L{{.*}}-_spilledValue<br>-; CHECK-NEXT: .short 0<br>-; CHECK-NEXT: .short 17<br>+; CHECK-LABEL:  .long L{{.*}}-_spilledValue<br>+; CHECK-NEXT:   .short 0<br>+; CHECK-NEXT:   .short 17<br>;<br>; Check that at least one is a spilled entry from RBP.<br>; Location: Indirect RBP + ...<br>-; CHECK:      .byte 3<br>-; CHECK-NEXT: .byte 8<br>-; CHECK-NEXT: .short 6<br>+; CHECK:        .byte 3<br>+; CHECK-NEXT:   .byte 8<br>+; CHECK-NEXT:   .short 6<br>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) {<br>entry:<br> 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)<br>@@ -202,15 +202,15 @@ entry:<br>;<br>; Verify 17 stack map entries.<br>;<br>-; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue<br>-; CHECK-NEXT:  .short 0<br>-; CHECK-NEXT:  .short 17<br>+; CHECK-LABEL:  .long L{{.*}}-_spilledStackMapValue<br>+; CHECK-NEXT:   .short 0<br>+; CHECK-NEXT:   .short 17<br>;<br>; Check that at least one is a spilled entry from RBP.<br>; Location: Indirect RBP + ...<br>-; CHECK:      .byte 3<br>-; CHECK-NEXT: .byte 8<br>-; CHECK-NEXT: .short 6<br>+; CHECK:        .byte 3<br>+; CHECK-NEXT:   .byte 8<br>+; CHECK-NEXT:   .short 6<br>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) {<br>entry:<br> 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)<br>@@ -219,16 +219,16 @@ entry:<br><br>; Spill a subregister stackmap operand.<br>;<br>-; CHECK-LABEL: .long L{{.*}}-_spillSubReg<br>-; CHECK-NEXT:  .short 0<br>+; CHECK-LABEL:  .long L{{.*}}-_spillSubReg<br>+; CHECK-NEXT:   .short 0<br>; 4 locations<br>-; CHECK-NEXT:  .short 1<br>+; CHECK-NEXT:   .short 1<br>;<br>; Check that the subregister operand is a 4-byte spill.<br>; Location: Indirect, 4-byte, RBP + ...<br>-; CHECK:      .byte 3<br>-; CHECK-NEXT: .byte 4<br>-; CHECK-NEXT: .short 6<br>+; CHECK:        .byte 3<br>+; CHECK-NEXT:   .byte 4<br>+; CHECK-NEXT:   .short 6<br>define void @spillSubReg(i64 %arg) #0 {<br>bb:<br> br i1 undef, label %bb1, label %bb2<br>@@ -259,23 +259,23 @@ bb61:<br>; Map a single byte subregister. There is no DWARF register number, so<br>; we expect the register to be encoded with the proper size and spill offset. We don't know which<br>;<br>-; CHECK-LABEL: .long L{{.*}}-_subRegOffset<br>-; CHECK-NEXT:  .short 0<br>+; CHECK-LABEL:  .long L{{.*}}-_subRegOffset<br>+; CHECK-NEXT:   .short 0<br>; 2 locations<br>-; CHECK-NEXT:  .short 2<br>+; CHECK-NEXT:   .short 2<br>;<br>; Check that the subregister operands are 1-byte spills.<br>; Location 0: Register, 4-byte, AL<br>-; CHECK-NEXT: .byte 1<br>-; CHECK-NEXT: .byte 1<br>-; CHECK-NEXT: .short 0<br>-; CHECK-NEXT: .long 0<br>+; CHECK-NEXT:   .byte 1<br>+; CHECK-NEXT:   .byte 1<br>+; CHECK-NEXT:   .short 0<br>+; CHECK-NEXT:   .long 0<br>;<br>; Location 1: Register, 4-byte, BL<br>-; CHECK-NEXT: .byte 1<br>-; CHECK-NEXT: .byte 1<br>-; CHECK-NEXT: .short 3<br>-; CHECK-NEXT: .long 0<br>+; CHECK-NEXT:   .byte 1<br>+; CHECK-NEXT:   .byte 1<br>+; CHECK-NEXT:   .short 3<br>+; CHECK-NEXT:   .long 0<br>define void @subRegOffset(i16 %arg) {<br> %v = mul i16 %arg, 5<br> %a0 = trunc i16 %v to i8<br>@@ -289,10 +289,10 @@ define void @subRegOffset(i16 %arg) {<br><br>; Map a constant value.<br>;<br>-; CHECK-LABEL: .long L{{.*}}-_liveConstant<br>-; CHECK-NEXT:  .short 0<br>+; CHECK-LABEL:  .long L{{.*}}-_liveConstant<br>+; CHECK-NEXT:   .short 0<br>; 1 location<br>-; CHECK-NEXT:  .short 1<br>+; CHECK-NEXT:   .short 1<br>; Loc 0: SmallConstant<br>; CHECK-NEXT:   .byte   4<br>; CHECK-NEXT:   .byte   8<br>@@ -316,9 +316,9 @@ define void @liveConstant() {<br>; CHECK-NEXT:   .byte<span class="Apple-tab-span" style="white-space: pre;">        </span>8<br>; CHECK-NEXT:   .short<span class="Apple-tab-span" style="white-space: pre;">       </span>6<br>; CHECK-NEXT:   .long<br>-; CHECK-NEXT:   .quad<br>+<br>; Callsite 17<br>-; CHECK-NEXT:   .long<span class="Apple-tab-span" style="white-space: pre;">  </span>L{{.*}}-_directFrameIdx<br>+; CHECK-LABEL:  .long<span class="Apple-tab-span" style="white-space: pre;">      </span>L{{.*}}-_directFrameIdx<br>; CHECK-NEXT:   .short<span class="Apple-tab-span" style="white-space: pre;"> </span>0<br>; 2 locations<br>; CHECK-NEXT:   .short<span class="Apple-tab-span" style="white-space: pre;">        </span>2<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</blockquote></div></blockquote></div><br></div></div></body></html>