[llvm] r197317 - [Stackmap] Liveness Analysis Pass

Hal Finkel hfinkel at anl.gov
Sat Dec 14 04:57:38 PST 2013


----- Original Message -----
> From: "Juergen Ributzka" <juergen at apple.com>
> To: llvm-commits at cs.uiuc.edu
> Sent: Saturday, December 14, 2013 12:53:06 AM
> Subject: [llvm] r197317 - [Stackmap] Liveness Analysis Pass
> 
> Author: ributzka
> Date: Sat Dec 14 00:53:06 2013
> New Revision: 197317
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=197317&view=rev
> Log:
> [Stackmap] Liveness Analysis Pass
> 
> This optional register liveness analysis pass can be enabled with
> either
> -enable-stackmap-liveness, -enable-patchpoint-liveness, or both.

This is obviously fine for experimentation, but what's the eventual plan for this? (do you want to add some parameter to the intrinsics to enable this, or some kind of CodeGenOpt flag?)

 -Hal

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

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list