<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>