From ebe69fe11e48d322045d5949c83283927a0d790b Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 23 Mar 2015 12:10:34 -0700 Subject: Update aosp/master LLVM for rebase to r230699. Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9 --- include/llvm/CodeGen/Analysis.h | 17 +- include/llvm/CodeGen/AsmPrinter.h | 54 +- include/llvm/CodeGen/BasicTTIImpl.h | 723 +++++++++++++++++++++ include/llvm/CodeGen/CallingConvLower.h | 63 +- include/llvm/CodeGen/CommandFlags.h | 5 + include/llvm/CodeGen/DIE.h | 587 +++++++++++++++++ include/llvm/CodeGen/FastISel.h | 11 +- include/llvm/CodeGen/ForwardControlFlowIntegrity.h | 1 - include/llvm/CodeGen/FunctionLoweringInfo.h | 16 +- include/llvm/CodeGen/GCMetadata.h | 295 ++++----- include/llvm/CodeGen/GCMetadataPrinter.h | 76 +-- include/llvm/CodeGen/GCStrategy.h | 254 ++++---- include/llvm/CodeGen/GCs.h | 32 +- include/llvm/CodeGen/ISDOpcodes.h | 23 +- include/llvm/CodeGen/LexicalScopes.h | 18 +- include/llvm/CodeGen/LinkAllCodegenComponents.h | 1 + include/llvm/CodeGen/LiveInterval.h | 226 ++++++- include/llvm/CodeGen/LiveIntervalAnalysis.h | 57 +- include/llvm/CodeGen/LiveIntervalUnion.h | 14 +- include/llvm/CodeGen/LivePhysRegs.h | 4 +- include/llvm/CodeGen/MachineDominanceFrontier.h | 4 +- include/llvm/CodeGen/MachineFrameInfo.h | 4 + include/llvm/CodeGen/MachineFunction.h | 22 +- include/llvm/CodeGen/MachineInstr.h | 25 +- include/llvm/CodeGen/MachineLoopInfo.h | 4 +- include/llvm/CodeGen/MachineModuleInfo.h | 37 +- include/llvm/CodeGen/MachinePassRegistry.h | 7 +- include/llvm/CodeGen/MachineRegisterInfo.h | 19 +- include/llvm/CodeGen/MachineSSAUpdater.h | 4 +- include/llvm/CodeGen/MachineScheduler.h | 1 - include/llvm/CodeGen/MachineValueType.h | 64 +- include/llvm/CodeGen/PBQP/Graph.h | 73 +-- include/llvm/CodeGen/PBQP/ReductionRules.h | 32 +- include/llvm/CodeGen/Passes.h | 86 +-- include/llvm/CodeGen/RegAllocPBQP.h | 132 +++- include/llvm/CodeGen/ScheduleDAG.h | 6 + include/llvm/CodeGen/SelectionDAG.h | 14 +- include/llvm/CodeGen/SelectionDAGISel.h | 2 +- include/llvm/CodeGen/SelectionDAGNodes.h | 127 +++- include/llvm/CodeGen/SlotIndexes.h | 2 +- include/llvm/CodeGen/StackMaps.h | 50 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 11 +- include/llvm/CodeGen/ValueTypes.td | 3 + include/llvm/CodeGen/VirtRegMap.h | 4 +- 44 files changed, 2605 insertions(+), 605 deletions(-) create mode 100644 include/llvm/CodeGen/BasicTTIImpl.h create mode 100644 include/llvm/CodeGen/DIE.h (limited to 'include/llvm/CodeGen') diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index 3132999..c4b94ed 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -31,10 +31,21 @@ class SDValue; class SelectionDAG; struct EVT; -/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence -/// of insertvalue or extractvalue indices that identify a member, return -/// the linearized index of the start of the member. +/// \brief Compute the linearized index of a member in a nested +/// aggregate/struct/array. /// +/// Given an LLVM IR aggregate type and a sequence of insertvalue or +/// extractvalue indices that identify a member, return the linearized index of +/// the start of the member, i.e the number of element in memory before the +/// seeked one. This is disconnected from the number of bytes. +/// +/// \param Ty is the type indexed by \p Indices. +/// \param Indices is an optional pointer in the indices list to the current +/// index. +/// \param IndicesEnd is the end of the indices list. +/// \param CurIndex is the current index in the recursion. +/// +/// \returns \p CurIndex plus the linear index in \p Ty the indices list. unsigned ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 25b99a2..ac224d8 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -44,8 +44,8 @@ class MachineModuleInfo; class MCAsmInfo; class MCCFIInstruction; class MCContext; +class MCExpr; class MCInst; -class MCInstrInfo; class MCSection; class MCStreamer; class MCSubtargetInfo; @@ -68,7 +68,6 @@ public: /// const MCAsmInfo *MAI; - const MCInstrInfo *MII; /// This is the context for the output file that we are streaming. This owns /// all of the global MC-related objects for the generated translation unit. MCContext &OutContext; @@ -98,6 +97,11 @@ public: /// default, this is equal to CurrentFnSym. MCSymbol *CurrentFnSymForSize; + /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of + /// its number of uses by other globals. + typedef std::pair GOTEquivUsePair; + DenseMap GlobalGOTEquivs; + private: // The garbage collection metadata printer table. void *GCMetadataPrinters; // Really a DenseMap. @@ -126,12 +130,13 @@ private: DwarfDebug *DD; protected: - explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); + explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); public: virtual ~AsmPrinter(); DwarfDebug *getDwarfDebug() { return DD; } + DwarfDebug *getDwarfDebug() const { return DD; } /// Return true if assembly output should contain comments. /// @@ -203,6 +208,8 @@ public: void emitCFIInstruction(const MachineInstr &MI); + void emitFrameAlloc(const MachineInstr &MI); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves(); @@ -234,13 +241,27 @@ public: /// void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const; - /// This method prints the label for the specified MachineBasicBlock, an - /// alignment (if present) and a comment describing it if appropriate. - void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Lower the specified LLVM Constant to an MCExpr. + const MCExpr *lowerConstant(const Constant *CV); /// \brief Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV); + /// \brief Unnamed constant global variables solely contaning a pointer to + /// another globals variable act like a global variable "proxy", or GOT + /// equivalents, i.e., it's only used to hold the address of the latter. One + /// optimization is to replace accesses to these proxies by using the GOT + /// entry for the final global instead. Hence, we select GOT equivalent + /// candidates among all the module global variables, avoid emitting them + /// unnecessarily and finally replace references to them by pc relative + /// accesses to GOT entries. + void computeGlobalGOTEquivs(Module &M); + + /// \brief Constant expressions using GOT equivalent globals may not be + /// eligible for PC relative GOT entry conversion, in such cases we need to + /// emit the proxies we previously omitted in EmitGlobalVariable. + void emitGlobalGOTEquivs(); + //===------------------------------------------------------------------===// // Overridable Hooks //===------------------------------------------------------------------===// @@ -264,6 +285,12 @@ public: /// function. virtual void EmitFunctionBodyEnd() {} + /// Targets can override this to emit stuff at the start of a basic block. + /// By default, this method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing it + /// if appropriate. + virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Targets can override this to emit stuff at the end of a basic block. virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} @@ -299,10 +326,10 @@ public: public: /// Return the MCSymbol corresponding to the assembler temporary label with /// the specified stem and unique ID. - MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const; + MCSymbol *GetTempSymbol(const Twine &Name, unsigned ID) const; /// Return an assembler temporary label with the specified stem. - MCSymbol *GetTempSymbol(Twine Name) const; + MCSymbol *GetTempSymbol(const Twine &Name) const; /// Return the MCSymbol for a private symbol with global value name as its /// base, with the specified suffix. @@ -397,7 +424,7 @@ public: const MCSymbol *SectionLabel) const; /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. - virtual unsigned getISAEncoding() { return 0; } + virtual unsigned getISAEncoding(const Function *) { return 0; } /// Emit a dwarf register operation for describing /// - a small value occupying only part of a register or @@ -423,9 +450,8 @@ public: unsigned PieceOffset = 0) const; /// EmitDwarfRegOp - Emit a dwarf register operation. - /// \param Indirect whether this is a register-indirect address - virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, - bool Indirect) const; + virtual void EmitDwarfRegOp(ByteStreamer &BS, + const MachineLocation &MLoc) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines @@ -465,6 +491,10 @@ public: unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS); + /// Let the target do anything it needs to do before emitting inlineasm. + /// \p StartInfo - the subtarget info before parsing inline asm + virtual void emitInlineAsmStart() const; + /// Let the target do anything it needs to do after emitting inlineasm. /// This callback can be used restore the original mode in case the /// inlineasm contains directives to switch modes. diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h new file mode 100644 index 0000000..ff85b06 --- /dev/null +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -0,0 +1,723 @@ +//===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides a helper that implements much of the TTI interface in +/// terms of the target-independent code generator and TargetLowering +/// interfaces. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BASICTTIIMPL_H +#define LLVM_CODEGEN_BASICTTIIMPL_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetTransformInfoImpl.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +namespace llvm { + +extern cl::opt PartialUnrollingThreshold; + +/// \brief Base class which can be used to help build a TTI implementation. +/// +/// This class provides as much implementation of the TTI interface as is +/// possible using the target independent parts of the code generator. +/// +/// In order to subclass it, your class must implement a getST() method to +/// return the subtarget, and a getTLI() method to return the target lowering. +/// We need these methods implemented in the derived class so that this class +/// doesn't have to duplicate storage for them. +template +class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { +private: + typedef TargetTransformInfoImplCRTPBase BaseT; + typedef TargetTransformInfo TTI; + + /// Estimate the overhead of scalarizing an instruction. Insert and Extract + /// are set if the result needs to be inserted and/or extracted from vectors. + unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) { + assert(Ty->isVectorTy() && "Can only scalarize vectors"); + unsigned Cost = 0; + + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + if (Insert) + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + if (Extract) + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + + return Cost; + } + + /// Estimate the cost overhead of SK_Alternate shuffle. + unsigned getAltShuffleOverhead(Type *Ty) { + assert(Ty->isVectorTy() && "Can only shuffle vectors"); + unsigned Cost = 0; + // Shuffle cost is equal to the cost of extracting element from its argument + // plus the cost of inserting them onto the result vector. + + // e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from + // index 0 of first vector, index 1 of second vector,index 2 of first + // vector and finally index 3 of second vector and insert them at index + // <0,1,2,3> of result vector. + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + return Cost; + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetSubtargetInfo *getST() const { + return static_cast(this)->getST(); + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetLoweringBase *getTLI() const { + return static_cast(this)->getTLI(); + } + +protected: + explicit BasicTTIImplBase(const TargetMachine *TM) + : BaseT(TM->getDataLayout()) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImplBase(const BasicTTIImplBase &Arg) + : BaseT(static_cast(Arg)) {} + BasicTTIImplBase(BasicTTIImplBase &&Arg) + : BaseT(std::move(static_cast(Arg))) {} + BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) { + BaseT::operator=(static_cast(RHS)); + return *this; + } + BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; + } + + /// \name Scalar TTI Implementations + /// @{ + + bool hasBranchDivergence() { return false; } + + bool isLegalAddImmediate(int64_t imm) { + return getTLI()->isLegalAddImmediate(imm); + } + + bool isLegalICmpImmediate(int64_t imm) { + return getTLI()->isLegalICmpImmediate(imm); + } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->isLegalAddressingMode(AM, Ty); + } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->getScalingFactorCost(AM, Ty); + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { + return getTLI()->isTruncateFree(Ty1, Ty2); + } + + bool isProfitableToHoist(Instruction *I) { + return getTLI()->isProfitableToHoist(I); + } + + bool isTypeLegal(Type *Ty) { + EVT VT = getTLI()->getValueType(Ty); + return getTLI()->isTypeLegal(VT); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) { + return BaseT::getIntrinsicCost(IID, RetTy, Arguments); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) { + if (IID == Intrinsic::cttz) { + if (getTLI()->isCheapToSpeculateCttz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + if (IID == Intrinsic::ctlz) { + if (getTLI()->isCheapToSpeculateCtlz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + return BaseT::getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getJumpBufAlignment() { return getTLI()->getJumpBufAlignment(); } + + unsigned getJumpBufSize() { return getTLI()->getJumpBufSize(); } + + bool shouldBuildLookupTables() { + const TargetLoweringBase *TLI = getTLI(); + return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other); + } + + bool haveFastSqrt(Type *Ty) { + const TargetLoweringBase *TLI = getTLI(); + EVT VT = TLI->getValueType(Ty); + return TLI->isTypeLegal(VT) && + TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); + } + + unsigned getFPOpCost(Type *Ty) { + // By default, FP instructions are no more expensive since they are + // implemented in HW. Target specific TTI can override this. + return TargetTransformInfo::TCC_Basic; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + const TargetLoweringBase *TLI = getTLI(); + switch (Opcode) { + default: break; + case Instruction::Trunc: { + if (TLI->isTruncateFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + case Instruction::ZExt: { + if (TLI->isZExtFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + } + + return BaseT::getOperationCost(Opcode, Ty, OpTy); + } + + void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) { + // This unrolling functionality is target independent, but to provide some + // motivation for its intended use, for x86: + + // According to the Intel 64 and IA-32 Architectures Optimization Reference + // Manual, Intel Core models and later have a loop stream detector (and + // associated uop queue) that can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have no more than 4 (8 for Nehalem and later) branches + // taken, and none of them may be calls. + // - The loop can have no more than 18 (28 for Nehalem and later) uops. + + // According to the Software Optimization Guide for AMD Family 15h + // Processors, models 30h-4fh (Steamroller and later) have a loop predictor + // and loop buffer which can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have fewer than 16 branches + // - The loop must have less than 40 uops in all executed loop branches + + // The number of taken branches in a loop is hard to estimate here, and + // benchmarking has revealed that it is better not to be conservative when + // estimating the branch count. As a result, we'll ignore the branch limits + // until someone finds a case where it matters in practice. + + unsigned MaxOps; + const TargetSubtargetInfo *ST = getST(); + if (PartialUnrollingThreshold.getNumOccurrences() > 0) + MaxOps = PartialUnrollingThreshold; + else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) + MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; + else + return; + + // Scan the loop: don't unroll loops with calls. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E; + ++I) { + BasicBlock *BB = *I; + + for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J) + if (isa(J) || isa(J)) { + ImmutableCallSite CS(J); + if (const Function *F = CS.getCalledFunction()) { + if (!static_cast(this)->isLoweredToCall(F)) + continue; + } + + return; + } + } + + // Enable runtime and partial unrolling up to the specified size. + UP.Partial = UP.Runtime = true; + UP.PartialThreshold = UP.PartialOptSizeThreshold = MaxOps; + } + + /// @} + + /// \name Vector TTI Implementations + /// @{ + + unsigned getNumberOfRegisters(bool Vector) { return 1; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor() { return 1; } + + unsigned getArithmeticInstrCost( + unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, + TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, + TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, + TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) { + // Check if any of the operands are vector operands. + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair LT = TLI->getTypeLegalizationCost(Ty); + + bool IsFloat = Ty->getScalarType()->isFloatingPointTy(); + // Assume that floating point arithmetic operations cost twice as much as + // integer operations. + unsigned OpCost = (IsFloat ? 2 : 1); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2 * OpCost; + return LT.first * 1 * OpCost; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2 * OpCost; + } + + // Else, assume that we need to scalarize this op. + if (Ty->isVectorTy()) { + unsigned Num = Ty->getVectorNumElements(); + unsigned Cost = static_cast(this) + ->getArithmeticInstrCost(Opcode, Ty->getScalarType()); + // return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(Ty, true, true) + Num * Cost; + } + + // We don't know anything about this scalar instruction. + return OpCost; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) { + if (Kind == TTI::SK_Alternate) { + return getAltShuffleOverhead(Tp); + } + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair SrcLT = TLI->getTypeLegalizationCost(Src); + std::pair DstLT = TLI->getTypeLegalizationCost(Dst); + + // Check for NOOP conversions. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Bitcast between types that are legalized to the same type are free. + if (Opcode == Instruction::BitCast || Opcode == Instruction::Trunc) + return 0; + } + + if (Opcode == Instruction::Trunc && + TLI->isTruncateFree(SrcLT.second, DstLT.second)) + return 0; + + if (Opcode == Instruction::ZExt && + TLI->isZExtFree(SrcLT.second, DstLT.second)) + return 0; + + // If the cast is marked as legal (or promote) then assume low cost. + if (SrcLT.first == DstLT.first && + TLI->isOperationLegalOrPromote(ISD, DstLT.second)) + return 1; + + // Handle scalar conversions. + if (!Src->isVectorTy() && !Dst->isVectorTy()) { + + // Scalar bitcasts are usually free. + if (Opcode == Instruction::BitCast) + return 0; + + // Just check the op cost. If the operation is legal then assume it costs + // 1. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return 1; + + // Assume that illegal scalar instruction are expensive. + return 4; + } + + // Check vector-to-vector casts. + if (Dst->isVectorTy() && Src->isVectorTy()) { + + // If the cast is between same-sized registers, then the check is simple. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Assume that Zext is done using AND. + if (Opcode == Instruction::ZExt) + return 1; + + // Assume that sext is done using SHL and SRA. + if (Opcode == Instruction::SExt) + return 2; + + // Just check the op cost. If the operation is legal then assume it + // costs + // 1 and multiply by the type-legalization overhead. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return SrcLT.first * 1; + } + + // If we are converting vectors and the operation is illegal, or + // if the vectors are legalized to different types, estimate the + // scalarization costs. + unsigned Num = Dst->getVectorNumElements(); + unsigned Cost = static_cast(this)->getCastInstrCost( + Opcode, Dst->getScalarType(), Src->getScalarType()); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting and extracting the values. + return getScalarizationOverhead(Dst, true, true) + Num * Cost; + } + + // We already handled vector-to-vector and scalar-to-scalar conversions. + // This + // is where we handle bitcast between vectors and scalars. We need to assume + // that the conversion is scalarized in one way or another. + if (Opcode == Instruction::BitCast) + // Illegal bitcasts are done by storing and loading from a stack slot. + return (Src->isVectorTy() ? getScalarizationOverhead(Src, false, true) + : 0) + + (Dst->isVectorTy() ? getScalarizationOverhead(Dst, true, false) + : 0); + + llvm_unreachable("Unhandled cast"); + } + + unsigned getCFInstrCost(unsigned Opcode) { + // Branches are assumed to be predicted. + return 0; + } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + // Selects on vectors are actually vector selects. + if (ISD == ISD::SELECT) { + assert(CondTy && "CondTy must exist"); + if (CondTy->isVectorTy()) + ISD = ISD::VSELECT; + } + + std::pair LT = TLI->getTypeLegalizationCost(ValTy); + + if (!(ValTy->isVectorTy() && !LT.second.isVector()) && + !TLI->isOperationExpand(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. Multiply + // by the type-legalization overhead. + return LT.first * 1; + } + + // Otherwise, assume that the cast is scalarized. + if (ValTy->isVectorTy()) { + unsigned Num = ValTy->getVectorNumElements(); + if (CondTy) + CondTy = CondTy->getScalarType(); + unsigned Cost = static_cast(this)->getCmpSelInstrCost( + Opcode, ValTy->getScalarType(), CondTy); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(ValTy, true, false) + Num * Cost; + } + + // Unknown scalar opcode. + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + std::pair LT = + getTLI()->getTypeLegalizationCost(Val->getScalarType()); + + return LT.first; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + assert(!Src->isVoidTy() && "Invalid type"); + std::pair LT = getTLI()->getTypeLegalizationCost(Src); + + // Assuming that all loads of legal types cost 1. + unsigned Cost = LT.first; + + if (Src->isVectorTy() && + Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) { + // This is a vector load that legalizes to a larger type than the vector + // itself. Unless the corresponding extending load or truncating store is + // legal, then this will scalarize. + TargetLowering::LegalizeAction LA = TargetLowering::Expand; + EVT MemVT = getTLI()->getValueType(Src, true); + if (MemVT.isSimple() && MemVT != MVT::Other) { + if (Opcode == Instruction::Store) + LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); + else + LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT); + } + + if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) { + // This is a vector load/store for some illegal type that is scalarized. + // We must account for the cost of building or decomposing the vector. + Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store, + Opcode == Instruction::Store); + } + } + + return Cost; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Tys) { + unsigned ISD = 0; + switch (IID) { + default: { + // Assume that we need to scalarize this intrinsic. + unsigned ScalarizationCost = 0; + unsigned ScalarCalls = 1; + if (RetTy->isVectorTy()) { + ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + } + for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { + if (Tys[i]->isVectorTy()) { + ScalarizationCost += getScalarizationOverhead(Tys[i], false, true); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + } + } + + return ScalarCalls + ScalarizationCost; + } + // Look for intrinsics that can be lowered directly or turned into a scalar + // intrinsic call. + case Intrinsic::sqrt: + ISD = ISD::FSQRT; + break; + case Intrinsic::sin: + ISD = ISD::FSIN; + break; + case Intrinsic::cos: + ISD = ISD::FCOS; + break; + case Intrinsic::exp: + ISD = ISD::FEXP; + break; + case Intrinsic::exp2: + ISD = ISD::FEXP2; + break; + case Intrinsic::log: + ISD = ISD::FLOG; + break; + case Intrinsic::log10: + ISD = ISD::FLOG10; + break; + case Intrinsic::log2: + ISD = ISD::FLOG2; + break; + case Intrinsic::fabs: + ISD = ISD::FABS; + break; + case Intrinsic::minnum: + ISD = ISD::FMINNUM; + break; + case Intrinsic::maxnum: + ISD = ISD::FMAXNUM; + break; + case Intrinsic::copysign: + ISD = ISD::FCOPYSIGN; + break; + case Intrinsic::floor: + ISD = ISD::FFLOOR; + break; + case Intrinsic::ceil: + ISD = ISD::FCEIL; + break; + case Intrinsic::trunc: + ISD = ISD::FTRUNC; + break; + case Intrinsic::nearbyint: + ISD = ISD::FNEARBYINT; + break; + case Intrinsic::rint: + ISD = ISD::FRINT; + break; + case Intrinsic::round: + ISD = ISD::FROUND; + break; + case Intrinsic::pow: + ISD = ISD::FPOW; + break; + case Intrinsic::fma: + ISD = ISD::FMA; + break; + case Intrinsic::fmuladd: + ISD = ISD::FMA; + break; + // FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free. + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + return 0; + case Intrinsic::masked_store: + return static_cast(this) + ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0); + case Intrinsic::masked_load: + return static_cast(this) + ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + } + + const TargetLoweringBase *TLI = getTLI(); + std::pair LT = TLI->getTypeLegalizationCost(RetTy); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2; + return LT.first * 1; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2; + } + + // If we can't lower fmuladd into an FMA estimate the cost as a floating + // point mul followed by an add. + if (IID == Intrinsic::fmuladd) + return static_cast(this) + ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + + static_cast(this) + ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); + + // Else, assume that we need to scalarize this intrinsic. For math builtins + // this will emit a costly libcall, adding call overhead and spills. Make it + // very expensive. + if (RetTy->isVectorTy()) { + unsigned Num = RetTy->getVectorNumElements(); + unsigned Cost = static_cast(this)->getIntrinsicInstrCost( + IID, RetTy->getScalarType(), Tys); + return 10 * Cost * Num; + } + + // This is going to be turned into a library call, make it expensive. + return 10; + } + + unsigned getNumberOfParts(Type *Tp) { + std::pair LT = getTLI()->getTypeLegalizationCost(Tp); + return LT.first; + } + + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; } + + unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) { + assert(Ty->isVectorTy() && "Expect a vector type"); + unsigned NumVecElts = Ty->getVectorNumElements(); + unsigned NumReduxLevels = Log2_32(NumVecElts); + unsigned ArithCost = + NumReduxLevels * + static_cast(this)->getArithmeticInstrCost(Opcode, Ty); + // Assume the pairwise shuffles add a cost. + unsigned ShuffleCost = + NumReduxLevels * (IsPairwise + 1) * + static_cast(this) + ->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts / 2, Ty); + return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true); + } + + /// @} +}; + +/// \brief Concrete BasicTTIImpl that can be used if no further customization +/// is needed. +class BasicTTIImpl : public BasicTTIImplBase { + typedef BasicTTIImplBase BaseT; + friend class BasicTTIImplBase; + + const TargetSubtargetInfo *ST; + const TargetLoweringBase *TLI; + + const TargetSubtargetInfo *getST() const { return ST; } + const TargetLoweringBase *getTLI() const { return TLI; } + +public: + explicit BasicTTIImpl(const TargetMachine *ST, Function &F); + + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImpl(const BasicTTIImpl &Arg) + : BaseT(static_cast(Arg)), ST(Arg.ST), TLI(Arg.TLI) {} + BasicTTIImpl(BasicTTIImpl &&Arg) + : BaseT(std::move(static_cast(Arg))), ST(std::move(Arg.ST)), + TLI(std::move(Arg.TLI)) {} + BasicTTIImpl &operator=(const BasicTTIImpl &RHS) { + BaseT::operator=(static_cast(RHS)); + ST = RHS.ST; + TLI = RHS.TLI; + return *this; + } + BasicTTIImpl &operator=(BasicTTIImpl &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + ST = std::move(RHS.ST); + TLI = std::move(RHS.TLI); + return *this; + } +}; + +} + +#endif diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 0b2ccc6..e2b744f 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -122,8 +122,8 @@ public: // There is no need to differentiate between a pending CCValAssign and other // kinds, as they are stored in a different list. static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, - LocInfo HTP) { - return getReg(ValNo, ValVT, 0, LocVT, HTP); + LocInfo HTP, unsigned ExtraInfo = 0) { + return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); } void convertToReg(unsigned RegNo) { @@ -146,6 +146,7 @@ public: unsigned getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + unsigned getExtraInfo() const { return Loc; } MVT getLocVT() const { return LocVT; } LocInfo getLocInfo() const { return HTP; } @@ -158,6 +159,16 @@ public: } }; +/// Describes a register that needs to be forwarded from the prologue to a +/// musttail call. +struct ForwardedRegister { + ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT) + : VReg(VReg), PReg(PReg), VT(VT) {} + unsigned VReg; + MCPhysReg PReg; + MVT VT; +}; + /// CCAssignFn - This function assigns a location for Val, updating State to /// reflect the change. It returns 'true' if it failed to handle Val. typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, @@ -302,13 +313,13 @@ public: /// produce a single value. void AnalyzeCallResult(MVT VT, CCAssignFn Fn); - /// getFirstUnallocated - Return the first unallocated register in the set, or - /// NumRegs if they are all allocated. - unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const { - for (unsigned i = 0; i != NumRegs; ++i) + /// getFirstUnallocated - Return the index of the first unallocated register + /// in the set, or Regs.size() if they are all allocated. + unsigned getFirstUnallocated(ArrayRef Regs) const { + for (unsigned i = 0; i < Regs.size(); ++i) if (!isAllocated(Regs[i])) return i; - return NumRegs; + return Regs.size(); } /// AllocateReg - Attempt to allocate one register. If it is not available, @@ -331,9 +342,9 @@ public: /// AllocateReg - Attempt to allocate one of the specified registers. If none /// are available, return zero. Otherwise, return the first one available, /// marking it and any aliases as allocated. - unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef Regs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -345,8 +356,12 @@ public: /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive /// registers. If this is not possible, return zero. Otherwise, return the first /// register of the block that were allocated, marking the entire block as allocated. - unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs, unsigned RegsRequired) { - for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired; ++StartIdx) { + unsigned AllocateRegBlock(ArrayRef Regs, unsigned RegsRequired) { + if (RegsRequired > Regs.size()) + return 0; + + for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired; + ++StartIdx) { bool BlockAvailable = true; // Check for already-allocated regs in this block for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { @@ -368,10 +383,9 @@ public: } /// Version of AllocateReg with list of registers to be shadowed. - unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs, - unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef Regs, const MCPhysReg *ShadowRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -401,8 +415,8 @@ public: /// Version of AllocateStack with list of extra registers to be shadowed. /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers. unsigned AllocateStack(unsigned Size, unsigned Align, - const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) { - for (unsigned i = 0; i < NumShadowRegs; ++i) + ArrayRef ShadowRegs) { + for (unsigned i = 0; i < ShadowRegs.size(); ++i) MarkAllocated(ShadowRegs[i]); return AllocateStack(Size, Align); } @@ -466,6 +480,19 @@ public: return PendingLocs; } + /// Compute the remaining unused register parameters that would be used for + /// the given value type. This is useful when varargs are passed in the + /// registers that normal prototyped parameters would be passed in, or for + /// implementing perfect forwarding. + void getRemainingRegParmsForType(SmallVectorImpl &Regs, MVT VT, + CCAssignFn Fn); + + /// Compute the set of registers that need to be preserved and forwarded to + /// any musttail calls. + void analyzeMustTailForwardedRegisters( + SmallVectorImpl &Forwards, ArrayRef RegParmTypes, + CCAssignFn Fn); + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 973c595..9f86429 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -207,6 +207,10 @@ FunctionSections("function-sections", cl::desc("Emit functions into separate sections"), cl::init(false)); +cl::opt UniqueSectionNames("unique-section-names", + cl::desc("Give unique names to every section"), + cl::init(true)); + cl::opt JTableType("jump-table-type", cl::desc("Choose the type of Jump-Instruction Table for jumptable."), @@ -284,6 +288,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.UniqueSectionNames = UniqueSectionNames; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h new file mode 100644 index 0000000..e310aef --- /dev/null +++ b/include/llvm/CodeGen/DIE.h @@ -0,0 +1,587 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { +class AsmPrinter; +class MCExpr; +class MCSymbol; +class raw_ostream; +class DwarfTypeUnit; + +//===--------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + dwarf::Attribute Attribute; + + /// Form - Dwarf form code. + /// + dwarf::Form Form; + +public: + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + + // Accessors. + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +//===--------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { + /// Unique number for node. + /// + unsigned Number; + + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag; + + /// Children - Whether or not this node has children. + /// + // This cheats a bit in all of the uses since the values in the standard + // are 0 and 1 for no children and children respectively. + bool Children; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector Data; + +public: + DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {} + + // Accessors. + dwarf::Tag getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + bool hasChildren() const { return Children; } + const SmallVectorImpl &getData() const { return Data; } + void setChildrenFlag(bool hasChild) { Children = hasChild; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIEValue; + +class DIE { +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Children DIEs. + /// + // This can't be a vector because pointer validity is requirent for the + // Parent pointer and DIEEntry. + // It can't be a list because some clients need pointer validity before + // the object has been added to any child list + // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may + // be more convoluted than beneficial. + std::vector> Children; + + DIE *Parent; + + /// Attribute values. + /// + SmallVector Values; + +protected: + DIE() + : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + +public: + explicit DIE(dwarf::Tag Tag) + : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + const DIEAbbrev &getAbbrev() const { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + dwarf::Tag getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector> &getChildren() const { + return Children; + } + const SmallVectorImpl &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// addChild - Add a child to the DIE. + /// + void addChild(std::unique_ptr Child) { + assert(!Child->getParent()); + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Child->Parent = this; + Children.push_back(std::move(Child)); + } + + /// findAttribute - Find a value in the DIE with the attribute given, + /// returns NULL if no such attribute exists. + DIEValue *findAttribute(dwarf::Attribute Attribute) const; + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEValue { + virtual void anchor(); + +public: + enum Type { + isInteger, + isString, + isExpr, + isLabel, + isDelta, + isEntry, + isTypeSignature, + isBlock, + isLoc, + isLocList, + }; + +protected: + /// Ty - Type of data stored in the value. + /// + Type Ty; + + explicit DIEValue(Type T) : Ty(T) {} + virtual ~DIEValue() {} + +public: + // Accessors + Type getType() const { return Ty; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; + +#ifndef NDEBUG + virtual void print(raw_ostream &O) const = 0; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { + uint64_t Integer; + +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + const int64_t SignedInt = Int; + if ((char)Int == SignedInt) + return dwarf::DW_FORM_data1; + if ((short)Int == SignedInt) + return dwarf::DW_FORM_data2; + if ((int)Int == SignedInt) + return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) + return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) + return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) + return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + uint64_t getValue() const { return Integer; } + + /// SizeOf - Determine size of integer value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEExpr - An expression DIE. +// +class DIEExpr : public DIEValue { + const MCExpr *Expr; + +public: + explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} + + /// EmitValue - Emit expression value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCExpr. + /// + const MCExpr *getValue() const { return Expr; } + + /// SizeOf - Determine size of expression value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELabel - A label DIE. +// +class DIELabel : public DIEValue { + const MCSymbol *Label; + +public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } + + /// SizeOf - Determine size of label value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + +public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEString - A container for string values. +/// +class DIEString : public DIEValue { + const DIEValue *Access; + StringRef Str; + +public: + DIEString(const DIEValue *Acc, StringRef S) + : DIEValue(isString), Access(Acc), Str(S) {} + + /// getString - Grab the string out of the object. + StringRef getString() const { return Str; } + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isString; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEEntry - A pointer to another debug information entry. An instance of +/// this class can also be used as a proxy for a debug information entry not +/// yet defined (ie. types.) +class DIEEntry : public DIEValue { + DIE &Entry; + +public: + explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { + } + + DIE &getEntry() const { return Entry; } + + /// EmitValue - Emit debug information entry offset. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } + + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(AsmPrinter *AP); + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// \brief A signature reference to a type unit. +class DIETypeSignature : public DIEValue { + const DwarfTypeUnit &Unit; + +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) + : DIEValue(isTypeSignature), Unit(Unit) {} + + /// \brief Emit type unit signature. + void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + + /// Returns size of a ref_sig8 entry. + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + assert(Form == dwarf::DW_FORM_ref_sig8); + return 8; + } + + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } +#ifndef NDEBUG + void print(raw_ostream &O) const override; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELoc - Represents an expression location. +// +class DIELoc : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIELoc() : DIEValue(isLoc), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm(unsigned DwarfVersion) const { + if (DwarfVersion > 3) + return dwarf::DW_FORM_exprloc; + // Pre-DWARF4 location expressions were blocks and not exprloc. + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLoc; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEBlock - Represents a block of values. +// +class DIEBlock : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIEBlock() : DIEValue(isBlock), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm() const { + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList : public DIEValue { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index b5405f9..1dca2ce 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -18,9 +18,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { @@ -76,6 +76,8 @@ public: unsigned ResultReg; unsigned NumResultRegs; + bool IsPatchPoint; + SmallVector OutVals; SmallVector OutFlags; SmallVector OutRegs; @@ -87,7 +89,7 @@ public: IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), - ResultReg(0), NumResultRegs(0) {} + ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, const Value *Target, ArgListTy &&ArgsList, @@ -162,6 +164,11 @@ public: return *this; } + CallLoweringInfo &setIsPatchPoint(bool Value = true) { + IsPatchPoint = Value; + return *this; + } + ArgListTy &getArgs() { return Args; } void clearOuts() { diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h index a6232c5..ec8e2ef 100644 --- a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h +++ b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h @@ -18,7 +18,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Pass.h" #include "llvm/Target/TargetOptions.h" - #include namespace llvm { diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 91f20d0..e12866e 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -20,8 +20,8 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -88,6 +88,12 @@ public: /// RegFixups - Registers which need to be replaced after isel is done. DenseMap RegFixups; + /// StatepointStackSlots - A list of temporary stack slots (frame indices) + /// used to spill values at a statepoint. We store them here to enable + /// reuse of the same stack slots across different statepoints in different + /// basic blocks. + SmallVector StatepointStackSlots; + /// MBB - The current block. MachineBasicBlock *MBB; @@ -200,6 +206,9 @@ public: return; unsigned Reg = It->second; + if (Reg == 0) + return; + LiveOutRegInfo.grow(Reg); LiveOutRegInfo[Reg].IsValid = false; } @@ -223,11 +232,6 @@ private: /// floating-point support. void ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI); -/// AddCatchInfo - Extract the personality and type infos from an eh.selector -/// call, and add them to the specified machine basic block. -void AddCatchInfo(const CallInst &I, - MachineModuleInfo *MMI, MachineBasicBlock *MBB); - /// AddLandingPadInfo - Extract the exception handling information from the /// landingpad instruction and add them to the specified machine module info. void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI, diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index ddcc823..357b2d8 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -34,168 +34,173 @@ #define LLVM_CODEGEN_GCMETADATA_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/GCStrategy.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" - #include namespace llvm { - class AsmPrinter; - class GCStrategy; - class Constant; - class MCSymbol; - - namespace GC { - /// PointKind - The type of a collector-safe point. - /// - enum PointKind { - Loop, ///< Instr is a loop (backwards branch). - Return, ///< Instr is a return instruction. - PreCall, ///< Instr is a call instruction. - PostCall ///< Instr is the return address of a call. - }; - } - - /// GCPoint - Metadata for a collector-safe point in machine code. +class AsmPrinter; +class Constant; +class MCSymbol; + +/// GCPoint - Metadata for a collector-safe point in machine code. +/// +struct GCPoint { + GC::PointKind Kind; ///< The kind of the safe point. + MCSymbol *Label; ///< A label. + DebugLoc Loc; + + GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) + : Kind(K), Label(L), Loc(DL) {} +}; + +/// GCRoot - Metadata for a pointer to an object managed by the garbage +/// collector. +struct GCRoot { + int Num; ///< Usually a frame index. + int StackOffset; ///< Offset from the stack pointer. + const Constant *Metadata; ///< Metadata straight from the call + ///< to llvm.gcroot. + + GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} +}; + +/// Garbage collection metadata for a single function. Currently, this +/// information only applies to GCStrategies which use GCRoot. +class GCFunctionInfo { +public: + typedef std::vector::iterator iterator; + typedef std::vector::iterator roots_iterator; + typedef std::vector::const_iterator live_iterator; + +private: + const Function &F; + GCStrategy &S; + uint64_t FrameSize; + std::vector Roots; + std::vector SafePoints; + + // FIXME: Liveness. A 2D BitVector, perhaps? + // + // BitVector Liveness; + // + // bool islive(int point, int root) = + // Liveness[point * SafePoints.size() + root] + // + // The bit vector is the more compact representation where >3.2% of roots + // are live per safe point (1.5% on 64-bit hosts). + +public: + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); + + /// getFunction - Return the function to which this metadata applies. /// - struct GCPoint { - GC::PointKind Kind; ///< The kind of the safe point. - MCSymbol *Label; ///< A label. - DebugLoc Loc; - - GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) - : Kind(K), Label(L), Loc(DL) {} - }; - - /// GCRoot - Metadata for a pointer to an object managed by the garbage - /// collector. - struct GCRoot { - int Num; ///< Usually a frame index. - int StackOffset; ///< Offset from the stack pointer. - const Constant *Metadata; ///< Metadata straight from the call - ///< to llvm.gcroot. + const Function &getFunction() const { return F; } - GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} - }; - - - /// GCFunctionInfo - Garbage collection metadata for a single function. + /// getStrategy - Return the GC strategy for the function. /// - class GCFunctionInfo { - public: - typedef std::vector::iterator iterator; - typedef std::vector::iterator roots_iterator; - typedef std::vector::const_iterator live_iterator; - - private: - const Function &F; - GCStrategy &S; - uint64_t FrameSize; - std::vector Roots; - std::vector SafePoints; - - // FIXME: Liveness. A 2D BitVector, perhaps? - // - // BitVector Liveness; - // - // bool islive(int point, int root) = - // Liveness[point * SafePoints.size() + root] - // - // The bit vector is the more compact representation where >3.2% of roots - // are live per safe point (1.5% on 64-bit hosts). - - public: - GCFunctionInfo(const Function &F, GCStrategy &S); - ~GCFunctionInfo(); - - /// getFunction - Return the function to which this metadata applies. - /// - const Function &getFunction() const { return F; } - - /// getStrategy - Return the GC strategy for the function. - /// - GCStrategy &getStrategy() { return S; } - - /// addStackRoot - Registers a root that lives on the stack. Num is the - /// stack object ID for the alloca (if the code generator is - // using MachineFrameInfo). - void addStackRoot(int Num, const Constant *Metadata) { - Roots.push_back(GCRoot(Num, Metadata)); - } - - /// removeStackRoot - Removes a root. - roots_iterator removeStackRoot(roots_iterator position) { - return Roots.erase(position); - } - - /// addSafePoint - Notes the existence of a safe point. Num is the ID of the - /// label just prior to the safe point (if the code generator is using - /// MachineModuleInfo). - void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { - SafePoints.push_back(GCPoint(Kind, Label, DL)); - } - - /// getFrameSize/setFrameSize - Records the function's frame size. - /// - uint64_t getFrameSize() const { return FrameSize; } - void setFrameSize(uint64_t S) { FrameSize = S; } - - /// begin/end - Iterators for safe points. - /// - iterator begin() { return SafePoints.begin(); } - iterator end() { return SafePoints.end(); } - size_t size() const { return SafePoints.size(); } - - /// roots_begin/roots_end - Iterators for all roots in the function. - /// - roots_iterator roots_begin() { return Roots.begin(); } - roots_iterator roots_end () { return Roots.end(); } - size_t roots_size() const { return Roots.size(); } - - /// live_begin/live_end - Iterators for live roots at a given safe point. - /// - live_iterator live_begin(const iterator &p) { return roots_begin(); } - live_iterator live_end (const iterator &p) { return roots_end(); } - size_t live_size(const iterator &p) const { return roots_size(); } - }; - - - /// GCModuleInfo - Garbage collection metadata for a whole module. - /// - class GCModuleInfo : public ImmutablePass { - typedef StringMap strategy_map_type; - typedef std::vector> list_type; - typedef DenseMap finfo_map_type; - - strategy_map_type StrategyMap; - list_type StrategyList; - finfo_map_type FInfoMap; + GCStrategy &getStrategy() { return S; } - GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); + /// addStackRoot - Registers a root that lives on the stack. Num is the + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). + void addStackRoot(int Num, const Constant *Metadata) { + Roots.push_back(GCRoot(Num, Metadata)); + } - public: - typedef list_type::const_iterator iterator; + /// removeStackRoot - Removes a root. + roots_iterator removeStackRoot(roots_iterator position) { + return Roots.erase(position); + } - static char ID; + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the + /// label just prior to the safe point (if the code generator is using + /// MachineModuleInfo). + void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { + SafePoints.push_back(GCPoint(Kind, Label, DL)); + } - GCModuleInfo(); + /// getFrameSize/setFrameSize - Records the function's frame size. + /// + uint64_t getFrameSize() const { return FrameSize; } + void setFrameSize(uint64_t S) { FrameSize = S; } - /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should - /// call it in doFinalization(). - /// - void clear(); + /// begin/end - Iterators for safe points. + /// + iterator begin() { return SafePoints.begin(); } + iterator end() { return SafePoints.end(); } + size_t size() const { return SafePoints.size(); } - /// begin/end - Iterators for used strategies. - /// - iterator begin() const { return StrategyList.begin(); } - iterator end() const { return StrategyList.end(); } + /// roots_begin/roots_end - Iterators for all roots in the function. + /// + roots_iterator roots_begin() { return Roots.begin(); } + roots_iterator roots_end() { return Roots.end(); } + size_t roots_size() const { return Roots.size(); } - /// get - Look up function metadata. - /// - GCFunctionInfo &getFunctionInfo(const Function &F); - }; + /// live_begin/live_end - Iterators for live roots at a given safe point. + /// + live_iterator live_begin(const iterator &p) { return roots_begin(); } + live_iterator live_end(const iterator &p) { return roots_end(); } + size_t live_size(const iterator &p) const { return roots_size(); } +}; + +/// An analysis pass which caches information about the entire Module. +/// Records both the function level information used by GCRoots and a +/// cache of the 'active' gc strategy objects for the current Module. +class GCModuleInfo : public ImmutablePass { + /// An owning list of all GCStrategies which have been created + SmallVector, 1> GCStrategyList; + /// A helper map to speedup lookups into the above list + StringMap GCStrategyMap; + +public: + /// Lookup the GCStrategy object associated with the given gc name. + /// Objects are owned internally; No caller should attempt to delete the + /// returned objects. + GCStrategy *getGCStrategy(const StringRef Name); + + /// List of per function info objects. In theory, Each of these + /// may be associated with a different GC. + typedef std::vector> FuncInfoVec; + + FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } + FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } + +private: + /// Owning list of all GCFunctionInfos associated with this Module + FuncInfoVec Functions; + + /// Non-owning map to bypass linear search when finding the GCFunctionInfo + /// associated with a particular Function. + typedef DenseMap finfo_map_type; + finfo_map_type FInfoMap; + +public: + typedef SmallVector,1>::const_iterator iterator; + + static char ID; + + GCModuleInfo(); + + /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should + /// call it in doFinalization(). + /// + void clear(); + /// begin/end - Iterators for used strategies. + /// + iterator begin() const { return GCStrategyList.begin(); } + iterator end() const { return GCStrategyList.end(); } + + /// get - Look up function metadata. This is currently assumed + /// have the side effect of initializing the associated GCStrategy. That + /// will soon change. + GCFunctionInfo &getFunctionInfo(const Function &F); +}; } #endif diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 4a6b5ac..2208470 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -26,49 +26,39 @@ namespace llvm { - class GCMetadataPrinter; - - /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the - /// defaults from Registry. - typedef Registry GCMetadataPrinterRegistry; - - /// GCMetadataPrinter - Emits GC metadata as assembly code. - /// - class GCMetadataPrinter { - public: - typedef GCStrategy::list_type list_type; - typedef GCStrategy::iterator iterator; - - private: - GCStrategy *S; - - friend class AsmPrinter; - - protected: - // May only be subclassed. - GCMetadataPrinter(); - - private: - GCMetadataPrinter(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - GCMetadataPrinter & - operator=(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - - public: - GCStrategy &getStrategy() { return *S; } - const Module &getModule() const { return S->getModule(); } - - /// begin/end - Iterate over the collected function metadata. - iterator begin() { return S->begin(); } - iterator end() { return S->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(AsmPrinter &AP); - - virtual void finishAssembly(AsmPrinter &AP); - - virtual ~GCMetadataPrinter(); - }; - +class GCMetadataPrinter; + +/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the +/// defaults from Registry. +typedef Registry GCMetadataPrinterRegistry; + +/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are +/// created, managed, and owned by the AsmPrinter. +class GCMetadataPrinter { +private: + GCStrategy *S; + friend class AsmPrinter; + +protected: + // May only be subclassed. + GCMetadataPrinter(); + +private: + GCMetadataPrinter(const GCMetadataPrinter &) = delete; + GCMetadataPrinter &operator=(const GCMetadataPrinter &) = delete; + +public: + GCStrategy &getStrategy() { return *S; } + + /// Called before the assembly for the module is generated by + /// the AsmPrinter (but after target specific hooks.) + virtual void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + /// Called after the assembly for the module is generated by + /// the AsmPrinter (but before target specific hooks) + virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + + virtual ~GCMetadataPrinter(); +}; } #endif diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 81e1f85..869f888 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -12,10 +12,15 @@ // specified in a function's 'gc' attribute. Algorithms are enabled by setting // flags in a subclass's constructor, and some virtual methods can be // overridden. -// -// When requested, the GCStrategy will be populated with data about each -// function which uses it. Specifically: -// +// +// GCStrategy is relevant for implementations using either gc.root or +// gc.statepoint based lowering strategies, but is currently focused mostly on +// options for gc.root. This will change over time. +// +// When requested by a subclass of GCStrategy, the gc.root implementation will +// populate GCModuleInfo and GCFunctionInfo with that about each Function in +// the Module that opts in to garbage collection. Specifically: +// // - Safe points // Garbage collection is generally only possible at certain points in code. // GCStrategy can request that the collector insert such points: @@ -23,7 +28,7 @@ // - At and after any call to a subroutine // - Before returning from the current function // - Before backwards branches (loops) -// +// // - Roots // When a reference to a GC-allocated object exists on the stack, it must be // stored in an alloca registered with llvm.gcoot. @@ -31,123 +36,142 @@ // This information can used to emit the metadata tables which are required by // the target garbage collector runtime. // +// When used with gc.statepoint, information about safepoint and roots can be +// found in the binary StackMap section after code generation. Safepoint +// placement is currently the responsibility of the frontend, though late +// insertion support is planned. gc.statepoint does not currently support +// custom stack map formats; such can be generated by parsing the standard +// stack map section if desired. +// +// The read and write barrier support can be used with either implementation. +// //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GCSTRATEGY_H -#define LLVM_CODEGEN_GCSTRATEGY_H +#ifndef LLVM_IR_GCSTRATEGY_H +#define LLVM_IR_GCSTRATEGY_H -#include "llvm/CodeGen/GCMetadata.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ADT/Optional.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Registry.h" #include namespace llvm { - - class GCStrategy; - - /// The GC strategy registry uses all the defaults from Registry. - /// - typedef Registry GCRegistry; - - /// GCStrategy describes a garbage collector algorithm's code generation - /// requirements, and provides overridable hooks for those needs which cannot - /// be abstractly described. - class GCStrategy { - public: - typedef std::vector> list_type; - typedef list_type::iterator iterator; - - private: - friend class GCModuleInfo; - const Module *M; - std::string Name; - - list_type Functions; - - protected: - unsigned NeededSafePoints; ///< Bitmask of required safe points. - bool CustomReadBarriers; ///< Default is to insert loads. - bool CustomWriteBarriers; ///< Default is to insert stores. - bool CustomRoots; ///< Default is to pass through to backend. - bool CustomSafePoints; ///< Default is to use NeededSafePoints - ///< to find safe points. - bool InitRoots; ///< If set, roots are nulled during lowering. - bool UsesMetadata; ///< If set, backend must emit metadata tables. - - public: - GCStrategy(); - - virtual ~GCStrategy() {} - - - /// getName - The name of the GC strategy, for debugging. - /// - const std::string &getName() const { return Name; } - - /// getModule - The module within which the GC strategy is operating. - /// - const Module &getModule() const { return *M; } - - /// needsSafePoitns - True if safe points of any kind are required. By - // default, none are recorded. - bool needsSafePoints() const { - return CustomSafePoints || NeededSafePoints != 0; - } - - /// needsSafePoint(Kind) - True if the given kind of safe point is - // required. By default, none are recorded. - bool needsSafePoint(GC::PointKind Kind) const { - return (NeededSafePoints & 1 << Kind) != 0; - } - - /// customWriteBarrier - By default, write barriers are replaced with simple - /// store instructions. If true, then - /// performCustomLowering must instead lower them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// customReadBarrier - By default, read barriers are replaced with simple - /// load instructions. If true, then - /// performCustomLowering must instead lower them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// customRoots - By default, roots are left for the code generator so it - /// can generate a stack map. If true, then - // performCustomLowering must delete them. - bool customRoots() const { return CustomRoots; } - - /// customSafePoints - By default, the GC analysis will find safe - /// points according to NeededSafePoints. If true, - /// then findCustomSafePoints must create them. - bool customSafePoints() const { return CustomSafePoints; } - - /// initializeRoots - If set, gcroot intrinsics should initialize their - // allocas to null before the first use. This is - // necessary for most GCs and is enabled by default. - bool initializeRoots() const { return InitRoots; } - - /// usesMetadata - If set, appropriate metadata tables must be emitted by - /// the back-end (assembler, JIT, or otherwise). - bool usesMetadata() const { return UsesMetadata; } - - /// begin/end - Iterators for function metadata. - /// - iterator begin() { return Functions.begin(); } - iterator end() { return Functions.end(); } - - /// insertFunctionMetadata - Creates metadata for a function. - /// - GCFunctionInfo *insertFunctionInfo(const Function &F); - - /// initializeCustomLowering/performCustomLowering - If any of the actions - /// are set to custom, performCustomLowering must be overriden to transform - /// the corresponding actions to LLVM IR. initializeCustomLowering is - /// optional to override. These are the only GCStrategy methods through - /// which the LLVM IR can be modified. - virtual bool initializeCustomLowering(Module &F); - virtual bool performCustomLowering(Function &F); - virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF); - }; - +namespace GC { +/// PointKind - The type of a collector-safe point. +/// +enum PointKind { + Loop, ///< Instr is a loop (backwards branch). + Return, ///< Instr is a return instruction. + PreCall, ///< Instr is a call instruction. + PostCall ///< Instr is the return address of a call. +}; +} + +/// GCStrategy describes a garbage collector algorithm's code generation +/// requirements, and provides overridable hooks for those needs which cannot +/// be abstractly described. GCStrategy objects must be looked up through +/// the Function. The objects themselves are owned by the Context and must +/// be immutable. +class GCStrategy { +private: + std::string Name; + friend class GCModuleInfo; + +protected: + bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, + /// if set, none of the other options can be + /// anything but their default values. + + unsigned NeededSafePoints; ///< Bitmask of required safe points. + bool CustomReadBarriers; ///< Default is to insert loads. + bool CustomWriteBarriers; ///< Default is to insert stores. + bool CustomRoots; ///< Default is to pass through to backend. + bool InitRoots; ///< If set, roots are nulled during lowering. + bool UsesMetadata; ///< If set, backend must emit metadata tables. + +public: + GCStrategy(); + virtual ~GCStrategy() {} + + /// Return the name of the GC strategy. This is the value of the collector + /// name string specified on functions which use this strategy. + const std::string &getName() const { return Name; } + + /// By default, write barriers are replaced with simple store + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcwrite. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// By default, read barriers are replaced with simple load + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcread. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// Returns true if this strategy is expecting the use of gc.statepoints, + /// and false otherwise. + bool useStatepoints() const { return UseStatepoints; } + + /** @name Statepoint Specific Properties */ + ///@{ + + /// If the value specified can be reliably distinguished, returns true for + /// pointers to GC managed locations and false for pointers to non-GC + /// managed locations. Note a GCStrategy can always return 'None' (i.e. an + /// empty optional indicating it can't reliably distinguish. + virtual Optional isGCManagedPointer(const Value *V) const { + return None; + } + ///@} + + /** @name GCRoot Specific Properties + * These properties and overrides only apply to collector strategies using + * GCRoot. + */ + ///@{ + + /// True if safe points of any kind are required. By default, none are + /// recorded. + bool needsSafePoints() const { return NeededSafePoints != 0; } + + /// True if the given kind of safe point is required. By default, none are + /// recorded. + bool needsSafePoint(GC::PointKind Kind) const { + return (NeededSafePoints & 1 << Kind) != 0; + } + + /// By default, roots are left for the code generator so it can generate a + /// stack map. If true, you must provide a custom pass to lower + /// calls to @llvm.gcroot. + bool customRoots() const { return CustomRoots; } + + /// If set, gcroot intrinsics should initialize their allocas to null + /// before the first use. This is necessary for most GCs and is enabled by + /// default. + bool initializeRoots() const { return InitRoots; } + + /// If set, appropriate metadata tables must be emitted by the back-end + /// (assembler, JIT, or otherwise). For statepoint, this method is + /// currently unsupported. The stackmap information can be found in the + /// StackMap section as described in the documentation. + bool usesMetadata() const { return UsesMetadata; } + + ///@} +}; + +/// Subclasses of GCStrategy are made available for use during compilation by +/// adding them to the global GCRegistry. This can done either within the +/// LLVM source tree or via a loadable plugin. An example registeration +/// would be: +/// static GCRegistry::Add X("custom-name", +/// "my custom supper fancy gc strategy"); +/// +/// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also +/// register your GCMetadataPrinter subclass with the +/// GCMetadataPrinterRegistery as well. +typedef Registry GCRegistry; } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index bb170c8..5bae41e 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -15,27 +15,29 @@ #define LLVM_CODEGEN_GCS_H namespace llvm { - class GCStrategy; - class GCMetadataPrinter; +class GCStrategy; +class GCMetadataPrinter; - /// FIXME: Collector instances are not useful on their own. These no longer - /// serve any purpose except to link in the plugins. +/// FIXME: Collector instances are not useful on their own. These no longer +/// serve any purpose except to link in the plugins. - /// Creates an ocaml-compatible garbage collector. - void linkOcamlGC(); +/// Creates an ocaml-compatible garbage collector. +void linkOcamlGC(); - /// Creates an ocaml-compatible metadata printer. - void linkOcamlGCPrinter(); +/// Creates an ocaml-compatible metadata printer. +void linkOcamlGCPrinter(); - /// Creates an erlang-compatible garbage collector. - void linkErlangGC(); +/// Creates an erlang-compatible garbage collector. +void linkErlangGC(); - /// Creates an erlang-compatible metadata printer. - void linkErlangGCPrinter(); +/// Creates an erlang-compatible metadata printer. +void linkErlangGCPrinter(); - /// Creates a shadow stack garbage collector. This collector requires no code - /// generator support. - void linkShadowStackGC(); +/// Creates a shadow stack garbage collector. This collector requires no code +/// generator support. +void linkShadowStackGC(); + +void linkStatepointExampleGC(); } #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index bbf0ad3..8a31f7e 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,6 +72,11 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover + /// intrinsic. Materializes the offset from the frame pointer of another + /// function to the result of llvm.frameallocate. + FRAME_ALLOC_RECOVER, + /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. READ_REGISTER, @@ -224,7 +229,14 @@ namespace ISD { SMULO, UMULO, /// Simple binary floating point operators. - FADD, FSUB, FMUL, FMA, FDIV, FREM, + FADD, FSUB, FMUL, FDIV, FREM, + + /// FMA - Perform a * b + c with no intermediate rounding step. + FMA, + + /// FMAD - Perform a * b + c, while getting the same result as the + /// separately rounded operations. + FMAD, /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This /// DAG node does not require that X and Y have the same type, just that the @@ -675,6 +687,11 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + // Masked load and store + MLOAD, MSTORE, + // Masked gather and scatter + MGATHER, MSCATTER, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, @@ -688,7 +705,7 @@ namespace ISD { /// which do not reference a specific memory location should be less than /// this value. Those that do must not be less than this value, and can /// be used with SelectionDAG::getMemIntrinsicNode. - static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed @@ -745,7 +762,7 @@ namespace ISD { LAST_LOADEXT_TYPE }; - NodeType getExtForLoadExtType(LoadExtType); + NodeType getExtForLoadExtType(bool IsFP, LoadExtType); //===--------------------------------------------------------------------===// /// ISD::CondCode enum - These are ordered carefully to make the bitfields diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 021fd98..b3a8405 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -19,14 +19,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" -#include #include +#include namespace llvm { class MachineInstr; @@ -48,6 +48,8 @@ public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { + assert((!D || D->isResolved()) && "Expected resolved node"); + assert((!I || I->isResolved()) && "Expected resolved node"); if (Parent) Parent->addChild(this); } @@ -116,8 +118,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - AssertingVH Desc; // Debug info descriptor. - AssertingVH InlinedAtLocation; // Location at which this + const MDNode *Desc; // Debug info descriptor. + const MDNode *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector Children; // Scopes defined in scope. @@ -178,9 +180,11 @@ public: return I != AbstractScopeMap.end() ? &I->second : nullptr; } - /// findInlinedScope - Find an inlined scope for the given DebugLoc or return - /// NULL. - LexicalScope *findInlinedScope(DebugLoc DL); + /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. + LexicalScope *findInlinedScope(const MDNode *N, const MDNode *IA) { + auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); + return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; + } /// findLexicalScope - Find regular lexical scope or return null. LexicalScope *findLexicalScope(const MDNode *N) { diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 372c294..e7ccbfa 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,6 +39,7 @@ namespace { llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); + llvm::linkStatepointExampleGC(); (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 6629e60..21634cb 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -27,6 +27,7 @@ #include "llvm/Support/Allocator.h" #include #include +#include namespace llvm { class CoalescerPair; @@ -119,6 +120,12 @@ namespace llvm { return isDeadDef() ? nullptr : LateVal; } + /// Returns the value alive at the end of the instruction, if any. This can + /// be a live-through value, a live def or a dead def. + VNInfo *valueOutOrDead() const { + return LateVal; + } + /// Return the value defined by this instruction, if any. This includes /// dead defs, it is the value created by the instruction's def operands. VNInfo *valueDefined() const { @@ -188,6 +195,12 @@ namespace llvm { Segments segments; // the liveness segments VNInfoList valnos; // value#'s + // The segment set is used temporarily to accelerate initial computation + // of live ranges of physical registers in computeRegUnitRange. + // After that the set is flushed to the segment vector and deleted. + typedef std::set SegmentSet; + SegmentSet *segmentSet; + typedef Segments::iterator iterator; iterator begin() { return segments.begin(); } iterator end() { return segments.end(); } @@ -204,6 +217,31 @@ namespace llvm { const_vni_iterator vni_begin() const { return valnos.begin(); } const_vni_iterator vni_end() const { return valnos.end(); } + /// Constructs a new LiveRange object. + LiveRange(bool UseSegmentSet = false) : segmentSet(nullptr) { + if (UseSegmentSet) + segmentSet = new SegmentSet(); + } + + /// Constructs a new LiveRange object by copying segments and valnos from + /// another LiveRange. + LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) + : segmentSet(nullptr) { + assert(Other.segmentSet == nullptr && + "Copying of LiveRanges with active SegmentSets is not supported"); + + // Duplicate valnos. + for (const VNInfo *VNI : Other.valnos) { + createValueCopy(VNI, Allocator); + } + // Now we can copy segments and remap their valnos. + for (const Segment &S : Other.segments) { + segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); + } + } + + ~LiveRange() { delete segmentSet; } + /// advanceTo - Advance the specified iterator to point to the Segment /// containing the specified position, or end() if the position is past the /// end of the range. If no Segment contains this position, but the @@ -217,6 +255,14 @@ namespace llvm { return I; } + const_iterator advanceTo(const_iterator I, SlotIndex Pos) const { + assert(I != end()); + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + /// find - Return an iterator pointing to the first segment that ends after /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster /// when searching large ranges. @@ -397,17 +443,21 @@ namespace llvm { /// scanning the Other range starting at I. bool overlapsFrom(const LiveRange &Other, const_iterator I) const; + /// Returns true if all segments of the @p Other live range are completely + /// covered by this live range. + /// Adjacent live ranges do not affect the covering:the liverange + /// [1,5](5,10] covers (3,7]. + bool covers(const LiveRange &Other) const; + /// Add the specified Segment to this range, merging segments as /// appropriate. This returns an iterator to the inserted segment (which /// may have grown since it was inserted). - iterator addSegment(Segment S) { - return addSegmentFrom(S, segments.begin()); - } + iterator addSegment(Segment S); - /// extendInBlock - If this range is live before Kill in the basic block - /// that starts at StartIdx, extend it to be live up to Kill, and return - /// the value. If there is no segment before Kill, return NULL. - VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); + /// If this range is live before @p Use in the basic block that starts at + /// @p StartIdx, extend it to be live up to @p Use, and return the value. If + /// there is no segment before @p Use, return nullptr. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Use); /// join - Join two live ranges (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS ranges as specified. If @@ -435,6 +485,12 @@ namespace llvm { removeSegment(S.start, S.end, RemoveDeadValNo); } + /// Remove segment pointed to by iterator @p I from this range. This does + /// not remove dead value numbers. + iterator removeSegment(iterator I) { + return segments.erase(I); + } + /// Query Liveness at Idx. /// The sub-instruction slot of Idx doesn't matter, only the instruction /// it refers to is considered. @@ -484,9 +540,9 @@ namespace llvm { /// Returns true if the live range is zero length, i.e. no live segments /// span instructions. It doesn't pay to spill such a range. bool isZeroLength(SlotIndexes *Indexes) const { - for (const_iterator i = begin(), e = end(); i != e; ++i) - if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() < - i->end.getBaseIndex()) + for (const Segment &S : segments) + if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() < + S.end.getBaseIndex()) return false; return true; } @@ -497,6 +553,12 @@ namespace llvm { return thisIndex < otherIndex; } + /// Flush segment set into the regular segment vector. + /// The method is to be called after the live range + /// has been created, if use of the segment set was + /// activated in the constructor of the live range. + void flushSegmentSet(); + void print(raw_ostream &OS) const; void dump() const; @@ -509,11 +571,13 @@ namespace llvm { void verify() const; #endif - private: + protected: + /// Append a segment to the list of segments. + void append(const LiveRange::Segment S); - iterator addSegmentFrom(Segment S, iterator From); - void extendSegmentEndTo(iterator I, SlotIndex NewEnd); - iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); + private: + friend class LiveRangeUpdater; + void addSegmentToSet(Segment S); void markValNoForDeletion(VNInfo *V); }; @@ -529,11 +593,124 @@ namespace llvm { public: typedef LiveRange super; + /// A live range for subregisters. The LaneMask specifies which parts of the + /// super register are covered by the interval. + /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()). + class SubRange : public LiveRange { + public: + SubRange *Next; + unsigned LaneMask; + + /// Constructs a new SubRange object. + SubRange(unsigned LaneMask) + : Next(nullptr), LaneMask(LaneMask) { + } + + /// Constructs a new SubRange object by copying liveness from @p Other. + SubRange(unsigned LaneMask, const LiveRange &Other, + BumpPtrAllocator &Allocator) + : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) { + } + }; + + private: + SubRange *SubRanges; ///< Single linked list of subregister live ranges. + + public: const unsigned reg; // the register or stack slot of this interval. float weight; // weight of this interval LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + : SubRanges(nullptr), reg(Reg), weight(Weight) {} + + ~LiveInterval() { + clearSubRanges(); + } + + template + class SingleLinkedListIterator { + T *P; + public: + SingleLinkedListIterator(T *P) : P(P) {} + SingleLinkedListIterator &operator++() { + P = P->Next; + return *this; + } + SingleLinkedListIterator &operator++(int) { + SingleLinkedListIterator res = *this; + ++*this; + return res; + } + bool operator!=(const SingleLinkedListIterator &Other) { + return P != Other.operator->(); + } + bool operator==(const SingleLinkedListIterator &Other) { + return P == Other.operator->(); + } + T &operator*() const { + return *P; + } + T *operator->() const { + return P; + } + }; + + typedef SingleLinkedListIterator subrange_iterator; + subrange_iterator subrange_begin() { + return subrange_iterator(SubRanges); + } + subrange_iterator subrange_end() { + return subrange_iterator(nullptr); + } + + typedef SingleLinkedListIterator const_subrange_iterator; + const_subrange_iterator subrange_begin() const { + return const_subrange_iterator(SubRanges); + } + const_subrange_iterator subrange_end() const { + return const_subrange_iterator(nullptr); + } + + iterator_range subranges() { + return make_range(subrange_begin(), subrange_end()); + } + + iterator_range subranges() const { + return make_range(subrange_begin(), subrange_end()); + } + + /// Creates a new empty subregister live range. The range is added at the + /// beginning of the subrange list; subrange iterators stay valid. + SubRange *createSubRange(BumpPtrAllocator &Allocator, unsigned LaneMask) { + SubRange *Range = new (Allocator) SubRange(LaneMask); + appendSubRange(Range); + return Range; + } + + /// Like createSubRange() but the new range is filled with a copy of the + /// liveness information in @p CopyFrom. + SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, unsigned LaneMask, + const LiveRange &CopyFrom) { + SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator); + appendSubRange(Range); + return Range; + } + + /// Returns true if subregister liveness information is available. + bool hasSubRanges() const { + return SubRanges != nullptr; + } + + /// Removes all subregister liveness information. + void clearSubRanges(); + + /// Removes all subranges without any segments (subranges without segments + /// are not considered valid and should only exist temporarily). + void removeEmptySubRanges(); + + /// Construct main live range by merging the SubRanges of @p LI. + void constructMainRangeFromSubranges(const SlotIndexes &Indexes, + VNInfo::Allocator &VNIAllocator); /// getSize - Returns the sum of sizes of all the LiveRange's. /// @@ -558,9 +735,26 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; + /// \brief Walks the interval and assert if any invariants fail to hold. + /// + /// Note that this is a no-op when asserts are disabled. +#ifdef NDEBUG + void verify(const MachineRegisterInfo *MRI = nullptr) const {} +#else + void verify(const MachineRegisterInfo *MRI = nullptr) const; +#endif + private: - LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; + LiveInterval& operator=(const LiveInterval& rhs) = delete; + + /// Appends @p Range to SubRanges list. + void appendSubRange(SubRange *Range) { + Range->Next = SubRanges; + SubRanges = Range; + } + /// Free memory held by SubRange. + void freeSubRange(SubRange *S); }; inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index f9bd317..dc52c0a 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -27,12 +27,15 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetRegisterInfo.h" #include #include namespace llvm { +extern cl::opt UseSegmentSetForPhysRegs; + class AliasAnalysis; class BitVector; class BlockFrequency; @@ -154,16 +157,11 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); - /// \brief Walk the values in the given interval and compute which ones - /// are dead. Dead values are not deleted, however: - /// - Dead PHIDef values are marked as unused. - /// - New dead machine instructions are added to the dead vector. - /// - CanSeparate is set to true if the interval may have been separated - /// into multiple connected components. - void computeDeadValues(LiveInterval *li, - LiveRange &LR, - bool *CanSeparate, - SmallVectorImpl *dead); + /// Specialized version of + /// shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) + /// that works on a subregister live range and only looks at uses matching + /// the lane mask of the subregister range. + void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by @@ -175,14 +173,15 @@ namespace llvm { /// See also LiveRangeCalc::extend(). void extendToIndices(LiveRange &LR, ArrayRef Indices); - /// pruneValue - If an LI value is live at Kill, prune its live range by - /// removing any liveness reachable from Kill. Add live range end points to + + /// If @p LR has a live value at @p Kill, prune its live range by removing + /// any liveness reachable from Kill. Add live range end points to /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the /// value's live range. /// /// Calling pruneValue() and extendToIndices() can be used to reconstruct /// SSA form after adding defs to a virtual register. - void pruneValue(LiveInterval *LI, SlotIndex Kill, + void pruneValue(LiveRange &LR, SlotIndex Kill, SmallVectorImpl *EndPoints); SlotIndexes *getSlotIndexes() const { @@ -381,7 +380,8 @@ namespace llvm { LiveRange *LR = RegUnitRanges[Unit]; if (!LR) { // Compute missing ranges on demand. - RegUnitRanges[Unit] = LR = new LiveRange(); + // Use segment set to speed-up initial computation of the live range. + RegUnitRanges[Unit] = LR = new LiveRange(UseSegmentSetForPhysRegs); computeRegUnitRange(*LR, Unit); } return *LR; @@ -397,6 +397,15 @@ namespace llvm { return RegUnitRanges[Unit]; } + /// Remove value numbers and related live segments starting at position + /// @p Pos that are part of any liverange of physical register @p Reg or one + /// of its subregisters. + void removePhysRegDefAt(unsigned Reg, SlotIndex Pos); + + /// Remove value number and related live segments of @p LI and its subranges + /// that start at position @p Pos. + void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos); + private: /// Compute live intervals for all virtual registers. void computeVirtRegs(); @@ -404,6 +413,16 @@ namespace llvm { /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); + /// Walk the values in @p LI and check for dead values: + /// - Dead PHIDef values are marked as unused. + /// - Dead operands are marked as such. + /// - Completely dead machine instructions are added to the @p dead vector + /// if it is not nullptr. + /// Returns true if any PHI value numbers have been removed which may + /// have separated the interval into multiple connected components. + bool computeDeadValues(LiveInterval &LI, + SmallVectorImpl *dead); + static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; @@ -413,6 +432,16 @@ namespace llvm { void computeRegUnitRange(LiveRange&, unsigned Unit); void computeVirtRegInterval(LiveInterval&); + + /// Helper function for repairIntervalsInRange(), walks backwards and + /// creates/modifies live segments in @p LR to match the operands found. + /// Only full operands or operands with subregisters matching @p LaneMask + /// are considered. + void repairOldRegInRange(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + const SlotIndex endIdx, LiveRange &LR, + unsigned Reg, unsigned LaneMask = ~0u); + class HMEditor; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 2f40509..967f0cb 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -84,10 +84,16 @@ public: bool changedSince(unsigned tag) const { return tag != Tag; } // Add a live virtual register to this union and merge its segments. - void unify(LiveInterval &VirtReg); + void unify(LiveInterval &VirtReg, const LiveRange &Range); + void unify(LiveInterval &VirtReg) { + unify(VirtReg, VirtReg); + } // Remove a live virtual register's segments from this union. - void extract(LiveInterval &VirtReg); + void extract(LiveInterval &VirtReg, const LiveRange &Range); + void extract(LiveInterval &VirtReg) { + extract(VirtReg, VirtReg); + } // Remove all inserted virtual registers. void clear() { Segments.clear(); ++Tag; } @@ -173,8 +179,8 @@ public: } private: - Query(const Query&) LLVM_DELETED_FUNCTION; - void operator=(const Query&) LLVM_DELETED_FUNCTION; + Query(const Query&) = delete; + void operator=(const Query&) = delete; }; // Array of LiveIntervalUnions. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 91e4ddc..4aa53a9 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -44,8 +44,8 @@ class LivePhysRegs { const TargetRegisterInfo *TRI; SparseSet LiveRegs; - LivePhysRegs(const LivePhysRegs&) LLVM_DELETED_FUNCTION; - LivePhysRegs &operator=(const LivePhysRegs&) LLVM_DELETED_FUNCTION; + LivePhysRegs(const LivePhysRegs&) = delete; + LivePhysRegs &operator=(const LivePhysRegs&) = delete; public: /// \brief Constructs a new empty LivePhysRegs set. LivePhysRegs() : TRI(nullptr), LiveRegs() {} diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index e099e71..4131194 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -26,8 +26,8 @@ public: typedef DominanceFrontierBase::iterator iterator; typedef DominanceFrontierBase::const_iterator const_iterator; - void operator=(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; - MachineDominanceFrontier(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; + void operator=(const MachineDominanceFrontier &) = delete; + MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; static char ID; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 1e7fee6..6677360 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -516,6 +516,10 @@ public: /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); + /// Allocates memory at a fixed, target-specific offset from the frame + /// pointer. Marks the function as having its frame address taken. + int CreateFrameAllocation(uint64_t Size); + /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 3271410..94610ca 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -72,6 +72,15 @@ private: /// MachineFunction is destroyed. struct MachineFunctionInfo { virtual ~MachineFunctionInfo(); + + /// \brief Factory function: default behavior is to call new using the + /// supplied allocator. + /// + /// This function can be overridden in a derive class. + template + static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) { + return new (Allocator.Allocate()) Ty(MF); + } }; class MachineFunction { @@ -136,8 +145,8 @@ class MachineFunction { /// True if the function includes any inline assembly. bool HasInlineAsm; - MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; - void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; + MachineFunction(const MachineFunction &) = delete; + void operator=(const MachineFunction&) = delete; public: MachineFunction(const Function *Fn, const TargetMachine &TM, unsigned FunctionNum, MachineModuleInfo &MMI); @@ -167,6 +176,13 @@ public: const TargetSubtargetInfo &getSubtarget() const { return *STI; } void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtargetInfo. In debug builds, it verifies that the object being + /// returned is of the correct type. + template const STC &getSubtarget() const { + return *static_cast(STI); + } + /// getRegInfo - Return information about the registers currently in use. /// MachineRegisterInfo &getRegInfo() { return *RegInfo; } @@ -239,7 +255,7 @@ public: template Ty *getInfo() { if (!MFInfo) - MFInfo = new (Allocator.Allocate()) Ty(*this); + MFInfo = Ty::template create(Allocator, *this); return static_cast(MFInfo); } diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index d20b45b..4ba4a97 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -93,10 +93,10 @@ private: DebugLoc debugLoc; // Source line information. - MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION; - void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION; + MachineInstr(const MachineInstr&) = delete; + void operator=(const MachineInstr&) = delete; // Use MachineFunction::DeleteMachineInstr() instead. - ~MachineInstr() LLVM_DELETED_FUNCTION; + ~MachineInstr() = delete; // Intrusive list support friend struct ilist_traits; @@ -110,8 +110,8 @@ private: /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. - MachineInstr(MachineFunction&, const MCInstrDesc &MCID, - const DebugLoc dl, bool NoImp = false); + MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl, + bool NoImp = false); // MachineInstrs are pool-allocated and owned by MachineFunction. friend class MachineFunction; @@ -242,7 +242,7 @@ public: /// getDebugLoc - Returns the debug location id of this MachineInstr. /// - DebugLoc getDebugLoc() const { return debugLoc; } + const DebugLoc &getDebugLoc() const { return debugLoc; } /// \brief Return the debug variable referenced by /// this DBG_VALUE instruction. @@ -1048,6 +1048,14 @@ public: bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); + /// Clear all dead flags on operands defining register @p Reg. + void clearRegisterDeads(unsigned Reg); + + /// Mark all subregister defs of register @p Reg with the undef flag. + /// This function is used when we determined to have a subregister def in an + /// otherwise undefined super register. + void addRegisterDefReadUndef(unsigned Reg); + /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. void addRegisterDefined(unsigned Reg, @@ -1139,7 +1147,10 @@ public: /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. /// - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { + debugLoc = std::move(dl); + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + } /// RemoveOperand - Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 4fbd46b..f7bcf45 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -74,8 +74,8 @@ class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase LI; friend class LoopBase; - void operator=(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; - MachineLoopInfo(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const MachineLoopInfo &) = delete; + MachineLoopInfo(const MachineLoopInfo &) = delete; public: static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6653333..f171df2 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -35,6 +35,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" @@ -66,6 +67,7 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector BeginLabels; // Labels prior to invoke. SmallVector EndLabels; // Labels after invoke. + SmallVector ClauseLabels; // Labels for each clause. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector TypeIds; // List of type ids (filters negative) @@ -161,14 +163,26 @@ class MachineModuleInfo : public ImmutablePass { /// to _fltused on Windows targets. bool UsesVAFloatArgument; + /// UsesMorestackAddr - True if the module calls the __morestack function + /// indirectly, as is required under the large code model on x86. This is used + /// to emit a definition of a symbol, __morestack_addr, containing the + /// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more + /// details. + bool UsesMorestackAddr; + + EHPersonality PersonalityTypeCache; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingVH Var; - TrackingVH Expr; + TrackingMDNodeRef Var; + TrackingMDNodeRef Expr; unsigned Slot; DebugLoc Loc; + + VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector VariableDbgInfoMapTy; VariableDbgInfoMapTy VariableDbgInfos; @@ -231,6 +245,14 @@ public: UsesVAFloatArgument = b; } + bool usesMorestackAddr() const { + return UsesMorestackAddr; + } + + void setUsesMorestackAddr(bool b) { + UsesMorestackAddr = b; + } + /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. @@ -312,6 +334,11 @@ public: /// void addCleanup(MachineBasicBlock *LandingPad); + /// Add a clause for a landing pad. Returns a new label for the clause. This + /// is used by EH schemes that have more than one landing pad. In this case, + /// each clause gets its own basic block. + MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned getTypeIDFor(const GlobalValue *TI); @@ -389,12 +416,14 @@ public: /// of one is required to emit exception handling info. const Function *getPersonality() const; + /// Classify the personality function amongst known EH styles. + EHPersonality getPersonalityType(); + /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) { - VariableDbgInfo Info = {Var, Expr, Slot, Loc}; - VariableDbgInfos.push_back(std::move(Info)); + VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index c962e68..57d1a6d 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -122,11 +122,12 @@ template class RegisterPassParser : public MachinePassRegistryListener, public cl::parser { public: - RegisterPassParser() {} + RegisterPassParser(cl::Option &O) + : cl::parser(O) {} ~RegisterPassParser() { RegistryClass::setListener(nullptr); } - void initialize(cl::Option &O) { - cl::parser::initialize(O); + void initialize() { + cl::parser::initialize(); // Add existing passes to option. for (RegistryClass *Node = RegistryClass::getList(); diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 2e7f034..abb04de 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -52,6 +52,9 @@ private: /// accurate when after this flag is cleared. bool TracksLiveness; + /// True if subregister liveness is tracked. + bool TracksSubRegLiveness; + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the @@ -120,8 +123,8 @@ private: /// second element. std::vector > LiveIns; - MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; - void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; + MachineRegisterInfo(const MachineRegisterInfo&) = delete; + void operator=(const MachineRegisterInfo&) = delete; public: explicit MachineRegisterInfo(const MachineFunction *MF); @@ -179,6 +182,12 @@ public: /// information. void invalidateLiveness() { TracksLiveness = false; } + bool tracksSubRegLiveness() const { return TracksSubRegLiveness; } + + void enableSubRegLiveness(bool Enable = true) { + TracksSubRegLiveness = Enable; + } + //===--------------------------------------------------------------------===// // Register Info //===--------------------------------------------------------------------===// @@ -584,7 +593,7 @@ public: /// virtual register, for example after removing instructions or splitting /// the live range. /// - bool recomputeRegClass(unsigned Reg, const TargetMachine&); + bool recomputeRegClass(unsigned Reg); /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. @@ -768,6 +777,10 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); + /// Returns a mask covering all bits that can appear in lane masks of + /// subregisters of the virtual register @p Reg. + unsigned getMaxLaneMaskForVReg(unsigned Reg) const; + /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 486a26e..5f988ad 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -107,8 +107,8 @@ public: private: unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); - void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; - MachineSSAUpdater(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; + void operator=(const MachineSSAUpdater&) = delete; + MachineSSAUpdater(const MachineSSAUpdater&) = delete; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index c5f66a8..a319401 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -80,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" - #include namespace llvm { diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index affacb0..7ad782f 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H #define LLVM_CODEGEN_MACHINEVALUETYPE_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -118,6 +119,7 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + FIRST_VALUETYPE = 0, // This is always the beginning of the list. LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. @@ -150,7 +152,11 @@ namespace llvm { // iPTR - An int value the size of the pointer of the current // target. This should only be used internal to tblgen! - iPTR = 255 + iPTR = 255, + + // Any - Any type. This is used for intrinsics that have overloadings. + // This is only for tblgen's consumption! + Any = 256 }; SimpleValueType SimpleTy; @@ -165,6 +171,12 @@ namespace llvm { bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + /// isValid - Return true if this is a valid simple valuetype. + bool isValid() const { + return (SimpleTy >= MVT::FIRST_VALUETYPE && + SimpleTy < MVT::LAST_VALUETYPE); + } + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && @@ -237,7 +249,8 @@ namespace llvm { /// isOverloaded - Return true if this is an overloaded type for TableGen. bool isOverloaded() const { - return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || + return (SimpleTy==MVT::Any || + SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); } @@ -372,6 +385,7 @@ namespace llvm { case iAny: case fAny: case vAny: + case Any: llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); @@ -575,6 +589,52 @@ namespace llvm { /// returned as Other, otherwise they are invalid. static MVT getVT(Type *Ty, bool HandleUnknown = false); + private: + /// A simple iterator over the MVT::SimpleValueType enum. + struct mvt_iterator { + SimpleValueType VT; + mvt_iterator(SimpleValueType VT) : VT(VT) {} + MVT operator*() const { return VT; } + bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; } + mvt_iterator& operator++() { + VT = (MVT::SimpleValueType)((int)VT + 1); + assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE && + "MVT iterator overflowed."); + return *this; + } + }; + /// A range of the MVT::SimpleValueType enum. + typedef iterator_range mvt_range; + + public: + /// SimpleValueType Iteration + /// @{ + static mvt_range all_valuetypes() { + return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE); + } + static mvt_range integer_valuetypes() { + return mvt_range(MVT::FIRST_INTEGER_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1)); + } + static mvt_range fp_valuetypes() { + return mvt_range(MVT::FIRST_FP_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1)); + } + static mvt_range vector_valuetypes() { + return mvt_range(MVT::FIRST_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1)); + } + static mvt_range integer_vector_valuetypes() { + return mvt_range( + MVT::FIRST_INTEGER_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1)); + } + static mvt_range fp_vector_valuetypes() { + return mvt_range( + MVT::FIRST_FP_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1)); + } + /// @} }; } // End llvm namespace diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index 4dc5674..efb723c 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -507,14 +507,14 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// @brief Set an edge's cost matrix. + /// @brief Update an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template - void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) { + void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs) { MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); if (Solver) - Solver->handleSetEdgeCosts(EId, *AllocatedCosts); + Solver->handleUpdateCosts(EId, *AllocatedCosts); getEdge(EId).Costs = AllocatedCosts; } @@ -548,14 +548,14 @@ namespace PBQP { /// @brief Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. - NodeId getEdgeNode1Id(EdgeId EId) { + NodeId getEdgeNode1Id(EdgeId EId) const { return getEdge(EId).getN1Id(); } /// @brief Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. - NodeId getEdgeNode2Id(EdgeId EId) { + NodeId getEdgeNode2Id(EdgeId EId) const { return getEdge(EId).getN2Id(); } @@ -672,69 +672,6 @@ namespace PBQP { Edges.clear(); FreeEdgeIds.clear(); } - - /// @brief Dump a graph to an output stream. - template - void dumpToStream(OStream &OS) { - OS << nodeIds().size() << " " << edgeIds().size() << "\n"; - - for (auto NId : nodeIds()) { - const Vector& V = getNodeCosts(NId); - OS << "\n" << V.getLength() << "\n"; - assert(V.getLength() != 0 && "Empty vector in graph."); - OS << V[0]; - for (unsigned i = 1; i < V.getLength(); ++i) { - OS << " " << V[i]; - } - OS << "\n"; - } - - for (auto EId : edgeIds()) { - NodeId N1Id = getEdgeNode1Id(EId); - NodeId N2Id = getEdgeNode2Id(EId); - assert(N1Id != N2Id && "PBQP graphs shound not have self-edges."); - const Matrix& M = getEdgeCosts(EId); - OS << "\n" << N1Id << " " << N2Id << "\n" - << M.getRows() << " " << M.getCols() << "\n"; - assert(M.getRows() != 0 && "No rows in matrix."); - assert(M.getCols() != 0 && "No cols in matrix."); - for (unsigned i = 0; i < M.getRows(); ++i) { - OS << M[i][0]; - for (unsigned j = 1; j < M.getCols(); ++j) { - OS << " " << M[i][j]; - } - OS << "\n"; - } - } - } - - /// @brief Dump this graph to dbgs(). - void dump() { - dumpToStream(dbgs()); - } - - /// @brief Print a representation of this graph in DOT format. - /// @param OS Output stream to print on. - template - void printDot(OStream &OS) { - OS << "graph {\n"; - for (auto NId : nodeIds()) { - OS << " node" << NId << " [ label=\"" - << NId << ": " << getNodeCosts(NId) << "\" ]\n"; - } - OS << " edge [ len=" << nodeIds().size() << " ]\n"; - for (auto EId : edgeIds()) { - OS << " node" << getEdgeNode1Id(EId) - << " -- node" << getEdgeNode2Id(EId) - << " [ label=\""; - const Matrix &EdgeCosts = getEdgeCosts(EId); - for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) { - OS << EdgeCosts.getRowAsVector(i) << "\\n"; - } - OS << "\" ]\n"; - } - OS << "}\n"; - } }; } // namespace PBQP diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index 21fde4d..d4a544b 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -132,9 +132,9 @@ namespace PBQP { } else { const Matrix &YZECosts = G.getEdgeCosts(YZEId); if (YNId == G.getEdgeNode1Id(YZEId)) { - G.setEdgeCosts(YZEId, Delta + YZECosts); + G.updateEdgeCosts(YZEId, Delta + YZECosts); } else { - G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts); + G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts); } } @@ -144,6 +144,25 @@ namespace PBQP { // TODO: Try to normalize newly added/modified edge. } +#ifndef NDEBUG + // Does this Cost vector have any register options ? + template + bool hasRegisterOptions(const VectorT &V) { + unsigned VL = V.getLength(); + + // An empty or spill only cost vector does not provide any register option. + if (VL <= 1) + return false; + + // If there are registers in the cost vector, but all of them have infinite + // costs, then ... there is no available register. + for (unsigned i = 1; i < VL; ++i) + if (V[i] != std::numeric_limits::infinity()) + return true; + + return false; + } +#endif // \brief Find a solution to a fully reduced graph by backpropagation. // @@ -170,6 +189,15 @@ namespace PBQP { RawVector v = G.getNodeCosts(NId); +#ifndef NDEBUG + // Although a conservatively allocatable node can be allocated to a register, + // spilling it may provide a lower cost solution. Assert here that spilling + // is done by choice, not because there were no register available. + if (G.getNodeMetadata(NId).wasConservativelyAllocatable()) + assert(hasRegisterOptions(v) && "A conservatively allocatable node " + "must have available register options"); +#endif + for (auto EId : G.adjEdgeIds(NId)) { const Matrix& edgeCosts = G.getEdgeCosts(EId); if (NId == G.getEdgeNode1Id(EId)) { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index b672d9d..65b17d3 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -105,6 +105,7 @@ private: AnalysisID StopAfter; bool Started; bool Stopped; + bool AddingMachinePasses; protected: TargetMachine *TM; @@ -213,7 +214,7 @@ public: /// /// This can also be used to plug a new MachineSchedStrategy into an instance /// of the standard ScheduleDAGMI: - /// return new ScheduleDAGMI(C, new MyStrategy(C)) + /// return new ScheduleDAGMI(C, make_unique(C), /* IsPostRA= */false) /// /// Return NULL to select the default (generic) machine scheduler. virtual ScheduleDAGInstrs * @@ -259,12 +260,9 @@ protected: return false; } - /// addPreRegAlloc - This method may be implemented by targets that want to - /// run passes immediately before register allocation. This should return - /// true if -print-machineinstrs should print after these passes. - virtual bool addPreRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + virtual void addPreRegAlloc() { } /// createTargetRegisterAllocator - Create the register allocator pass for /// this target at the current optimization level. @@ -290,24 +288,16 @@ protected: return false; } - /// addPostRegAlloc - This method may be implemented by targets that want to - /// run passes after register allocation pass pipeline but before - /// prolog-epilog insertion. This should return true if -print-machineinstrs - /// should print after these passes. - virtual bool addPostRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + virtual void addPostRegAlloc() { } /// Add passes that optimize machine instructions after register allocation. virtual void addMachineLateOptimization(); - /// addPreSched2 - This method may be implemented by targets that want to - /// run passes after prolog-epilog insertion and before the second instruction - /// scheduling pass. This should return true if -print-machineinstrs should - /// print after these passes. - virtual bool addPreSched2() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + virtual void addPreSched2() { } /// addGCPasses - Add late codegen passes that analyze code for garbage /// collection. This should return true if GC info should be printed after @@ -317,24 +307,30 @@ protected: /// Add standard basic block placement passes. virtual void addBlockPlacement(); - /// addPreEmitPass - This pass may be implemented by targets that want to run - /// passes immediately before machine code is emitted. This should return - /// true if -print-machineinstrs should print out the code after the passes. - virtual bool addPreEmitPass() { - return false; - } + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + virtual void addPreEmitPass() { } /// Utilities for targets to add passes to the pass manager. /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. - AnalysisID addPass(AnalysisID PassID); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, + bool printAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. - void addPass(Pass *P); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. @@ -343,7 +339,14 @@ protected: /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. /// - void printAndVerify(const char *Banner); + void printAndVerify(const std::string &Banner); + + /// Add a pass to print the machine function if printing is enabled. + void addPrintPass(const std::string &Banner); + + /// Add a pass to perform basic verification of the machine function if + /// verification is enabled. + void addVerifyPass(const std::string &Banner); }; } // namespace llvm @@ -351,13 +354,6 @@ protected: namespace llvm { FunctionPass *createAtomicExpandPass(const TargetMachine *TM); - /// \brief Create a basic TargetTransformInfo analysis pass. - /// - /// This pass implements the target transform info analysis using the target - /// independent information available to the LLVM code generator. - ImmutablePass * - createBasicTargetTransformInfoPass(const TargetMachine *TM); - /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either @@ -514,11 +510,15 @@ namespace llvm { /// information. extern char &MachineBlockPlacementStatsID; - /// GCLowering Pass - Performs target-independent LLVM IR transformations for - /// highly portable strategies. - /// + /// GCLowering Pass - Used by gc.root to perform its default lowering + /// operations. FunctionPass *createGCLoweringPass(); + /// ShadowStackGCLowering - Implements the custom lowering mechanism + /// used by the shadow stack GC. Only runs on functions which opt in to + /// the shadow stack collector. + FunctionPass *createShadowStackGCLoweringPass(); + /// GCMachineCodeAnalysis - Target-independent pass to mark safe points /// in machine code. Must be added very late during code generation, just /// prior to output, and importantly after all CFG transformations (such as @@ -560,12 +560,16 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// - FunctionPass *createMachineVerifierPass(const char *Banner = nullptr); + FunctionPass *createMachineVerifierPass(const std::string& Banner); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. FunctionPass *createDwarfEHPass(const TargetMachine *TM); + /// createWinEHPass - Prepares personality functions used by MSVC on Windows, + /// in addition to the Itanium LSDA based personalities. + FunctionPass *createWinEHPass(const TargetMachine *TM); + /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 540af08..c7bb07b 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -17,12 +17,15 @@ #define LLVM_CODEGEN_REGALLOCPBQP_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/CodeGen/PBQP/CostAllocator.h" #include "llvm/CodeGen/PBQP/ReductionRules.h" +#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { + +class raw_ostream; + namespace PBQP { namespace RegAlloc { @@ -177,23 +180,38 @@ class NodeMetadata { public: typedef RegAlloc::AllowedRegVector AllowedRegVector; - typedef enum { Unprocessed, - OptimallyReducible, - ConservativelyAllocatable, - NotProvablyAllocatable } ReductionState; + // The node's reduction state. The order in this enum is important, + // as it is assumed nodes can only progress up (i.e. towards being + // optimally reducible) when reducing the graph. + typedef enum { + Unprocessed, + NotProvablyAllocatable, + ConservativelyAllocatable, + OptimallyReducible + } ReductionState; NodeMetadata() : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), - VReg(0) {} + VReg(0) +#ifndef NDEBUG + , everConservativelyAllocatable(false) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. NodeMetadata(const NodeMetadata &Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), - AllowedRegs(Other.AllowedRegs) { - std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], - &OptUnsafeEdges[0]); + AllowedRegs(Other.AllowedRegs) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + { + if (NumOpts > 0) { + std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], + &OptUnsafeEdges[0]); + } } // FIXME: Re-implementing default behavior to work around MSVC. Remove once @@ -201,7 +219,11 @@ public: NodeMetadata(NodeMetadata &&Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg), - AllowedRegs(std::move(Other.AllowedRegs)) {} + AllowedRegs(std::move(Other.AllowedRegs)) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. @@ -214,6 +236,9 @@ public: OptUnsafeEdges.get()); VReg = Other.VReg; AllowedRegs = Other.AllowedRegs; +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -226,6 +251,9 @@ public: OptUnsafeEdges = std::move(Other.OptUnsafeEdges); VReg = Other.VReg; AllowedRegs = std::move(Other.AllowedRegs); +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -243,10 +271,21 @@ public: } ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { this->RS = RS; } + void setReductionState(ReductionState RS) { + assert(RS >= this->RS && "A node's reduction state can not be downgraded"); + this->RS = RS; + +#ifndef NDEBUG + // Remember this state to assert later that a non-infinite register + // option was available. + if (RS == ConservativelyAllocatable) + everConservativelyAllocatable = true; +#endif + } + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); + DeniedOpts += Transpose ? MD.getWorstRow() : MD.getWorstCol(); const bool* UnsafeOpts = Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); for (unsigned i = 0; i < NumOpts; ++i) @@ -254,7 +293,7 @@ public: } void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); + DeniedOpts -= Transpose ? MD.getWorstRow() : MD.getWorstCol(); const bool* UnsafeOpts = Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); for (unsigned i = 0; i < NumOpts; ++i) @@ -267,6 +306,12 @@ public: &OptUnsafeEdges[NumOpts]); } +#ifndef NDEBUG + bool wasConservativelyAllocatable() const { + return everConservativelyAllocatable; + } +#endif + private: ReductionState RS; unsigned NumOpts; @@ -274,6 +319,10 @@ private: std::unique_ptr OptUnsafeEdges; unsigned VReg; GraphMetadata::AllowedRegVecRef AllowedRegs; + +#ifndef NDEBUG + bool everConservativelyAllocatable; +#endif }; class RegAllocSolverImpl { @@ -307,6 +356,8 @@ public: } void handleAddNode(NodeId NId) { + assert(G.getNodeCosts(NId).getLength() > 1 && + "PBQP Graph should not contain single or zero-option nodes"); G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); } void handleRemoveNode(NodeId NId) {} @@ -326,15 +377,7 @@ public: NodeMetadata& NMd = G.getNodeMetadata(NId); const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } + promote(NId, NMd); } void handleReconnectEdge(EdgeId EId, NodeId NId) { @@ -343,20 +386,44 @@ public: NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); } - void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { - handleRemoveEdge(EId); - + void handleUpdateCosts(EdgeId EId, const Matrix& NewCosts) { NodeId N1Id = G.getEdgeNode1Id(EId); NodeId N2Id = G.getEdgeNode2Id(EId); NodeMetadata& N1Md = G.getNodeMetadata(N1Id); NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + bool Transpose = N1Id != G.getEdgeNode1Id(EId); + + // Metadata are computed incrementally. First, update them + // by removing the old cost. + const MatrixMetadata& OldMMd = G.getEdgeCosts(EId).getMetadata(); + N1Md.handleRemoveEdge(OldMMd, Transpose); + N2Md.handleRemoveEdge(OldMMd, !Transpose); + + // And update now the metadata with the new cost. const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); - N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + N1Md.handleAddEdge(MMd, Transpose); + N2Md.handleAddEdge(MMd, !Transpose); + + // As the metadata may have changed with the update, the nodes may have + // become ConservativelyAllocatable or OptimallyReducible. + promote(N1Id, N1Md); + promote(N2Id, N2Md); } private: + void promote(NodeId NId, NodeMetadata& NMd) { + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + void removeFromCurrentSet(NodeId NId) { switch (G.getNodeMetadata(NId).getReductionState()) { case NodeMetadata::Unprocessed: break; @@ -497,6 +564,17 @@ private: typedef PBQP::Graph BaseT; public: PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} + + /// @brief Dump this graph to dbgs(). + void dump() const; + + /// @brief Dump this graph to an output stream. + /// @param OS Output stream to print on. + void dump(raw_ostream &OS) const; + + /// @brief Print a representation of this graph in DOT format. + /// @param OS Output stream to print on. + void printDot(raw_ostream &OS) const; }; inline Solution solve(PBQPRAGraph& G) { diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 5a65d59..80aee8c 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -190,6 +190,12 @@ namespace llvm { return getKind() == Order && Contents.OrdKind == Barrier; } + /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory + /// dependence. + bool isNormalMemoryOrBarrier() const { + return (isNormalMemory() || isBarrier()); + } + /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index fbdaf0d..dc1c80d 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -115,8 +115,8 @@ class SDDbgInfo { typedef DenseMap > DbgValMapType; DbgValMapType DbgValMap; - void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; - SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; + void operator=(const SDDbgInfo&) = delete; + SDDbgInfo(const SDDbgInfo&) = delete; public: SDDbgInfo() {} @@ -262,8 +262,8 @@ private: DenseSet &visited, int level, bool &printed); - void operator=(const SelectionDAG&) LLVM_DELETED_FUNCTION; - SelectionDAG(const SelectionDAG&) LLVM_DELETED_FUNCTION; + void operator=(const SelectionDAG&) = delete; + SelectionDAG(const SelectionDAG&) = delete; public: explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); @@ -866,6 +866,12 @@ public: SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); + SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + SDValue Mask, SDValue Src0, EVT MemVT, + MachineMemOperand *MMO, ISD::LoadExtType); + SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, + SDValue Ptr, SDValue Mask, EVT MemVT, + MachineMemOperand *MMO, bool IsTrunc); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 2639402..d53e66d 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -18,8 +18,8 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Pass.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { class FastISel; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 4715827..0b6240f 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,7 +19,6 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" @@ -27,6 +26,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/ValueTypes.h" @@ -145,7 +145,7 @@ public: bool operator<(const SDValue &O) const { return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); } - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Node != nullptr; } @@ -184,7 +184,7 @@ public: inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; - inline const DebugLoc getDebugLoc() const; + inline const DebugLoc &getDebugLoc() const; inline void dump() const; inline void dumpr() const; @@ -259,8 +259,8 @@ class SDUse { /// this operand. SDUse **Prev, *Next; - SDUse(const SDUse &U) LLVM_DELETED_FUNCTION; - void operator=(const SDUse &U) LLVM_DELETED_FUNCTION; + SDUse(const SDUse &U) = delete; + void operator=(const SDUse &U) = delete; public: SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {} @@ -476,11 +476,11 @@ public: void setIROrder(unsigned Order) { IROrder = Order; } /// getDebugLoc - Return the source location info. - const DebugLoc getDebugLoc() const { return debugLoc; } + const DebugLoc &getDebugLoc() const { return debugLoc; } /// setDebugLoc - Set source location info. Try to avoid this, putting /// it in the constructor is preferable. - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); } /// use_iterator - This class provides iterator support for SDUse /// operands that use a specific SDNode. @@ -754,19 +754,20 @@ protected: return Ret; } - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs, + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, ArrayRef Ops) - : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), - SubclassData(0), NodeId(-1), - OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), - ValueList(VTs.VTs), UseList(nullptr), - NumOperands(Ops.size()), NumValues(VTs.NumVTs), - debugLoc(dl), IROrder(Order) { + : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), + SubclassData(0), NodeId(-1), + OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), + ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), + NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); for (unsigned i = 0; i != Ops.size(); ++i) { + assert(OperandList && "no operands available"); OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } @@ -775,11 +776,12 @@ protected: /// This constructor adds no operands itself; operands can be /// set later with InitOperands. - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs) - : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), - UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), - IROrder(Order) { + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) + : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), + SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), + UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(std::move(dl)), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); } @@ -942,7 +944,7 @@ inline bool SDValue::use_empty() const { inline bool SDValue::hasOneUse() const { return Node->hasNUsesOfValue(1, ResNo); } -inline const DebugLoc SDValue::getDebugLoc() const { +inline const DebugLoc &SDValue::getDebugLoc() const { return Node->getDebugLoc(); } inline void SDValue::dump() const { @@ -1177,6 +1179,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || + N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE || N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } @@ -1413,6 +1417,12 @@ public: /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Value->isNaN(); } + /// isInfinity - Return true if the value is an infinity + bool isInfinity() const { return Value->isInfinity(); } + + /// isNegative - Return true if the value is negative. + bool isNegative() const { return Value->isNegative(); } + /// isExactlyValue - We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of @@ -1601,7 +1611,7 @@ public: /// BUILD_VECTORs. class BuildVectorSDNode : public SDNode { // These are constructed as SDNodes and then cast to BuildVectorSDNodes. - explicit BuildVectorSDNode() LLVM_DELETED_FUNCTION; + explicit BuildVectorSDNode() = delete; public: /// isConstantSplat - Check if this is a constant splat, and if so, find the /// smallest element size that splats the vector. If MinSplatBits is @@ -1926,6 +1936,81 @@ public: } }; +/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and +/// MSTORE nodes +/// +class MaskedLoadStoreSDNode : public MemSDNode { + // Operands + SDUse Ops[4]; +public: + friend class SelectionDAG; + MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + InitOperands(Ops, Operands, numOperands); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value + // MaskedStoreSDNode (Chain, ptr, mask, data) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getMask() const { return getOperand(2); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE; + } +}; + +/// MaskedLoadSDNode - This class is used to represent an MLOAD node +/// +class MaskedLoadSDNode : public MaskedLoadStoreSDNode { +public: + friend class SelectionDAG; + MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy, + EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)ETy; + } + + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(SubclassData & 3); + } + const SDValue &getSrc0() const { return getOperand(3); } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD; + } +}; + +/// MaskedStoreSDNode - This class is used to represent an MSTORE node +/// +class MaskedStoreSDNode : public MaskedLoadStoreSDNode { + +public: + friend class SelectionDAG; + MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; + } + /// isTruncatingStore - Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return SubclassData & 1; } + + const SDValue &getValue() const { return getOperand(3); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSTORE; + } +}; + /// MachineSDNode - An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 00bb22b..9d6d6f5 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -162,7 +162,7 @@ namespace llvm { } /// Return true for a valid index. - LLVM_EXPLICIT operator bool() const { return isValid(); } + explicit operator bool() const { return isValid(); } /// Print this index to the given raw_ostream. void print(raw_ostream &os) const; diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index e343980..4e48afe 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -81,6 +81,52 @@ public: unsigned getNextScratchIdx(unsigned StartIdx = 0) const; }; +/// MI-level Statepoint operands +/// +/// Statepoint operands take the form: +/// , , [call arguments], +/// , , +/// , , [other args], +/// [gc values] +class StatepointOpers { +private: + enum { + NCallArgsPos = 0, + CallTargetPos = 1 + }; + +public: + explicit StatepointOpers(const MachineInstr *MI): + MI(MI) { } + + /// Get starting index of non call related arguments + /// (statepoint flags, vm state and gc state). + unsigned getVarIdx() const { + return MI->getOperand(NCallArgsPos).getImm() + 2; + } + + /// Returns the index of the operand containing the number of non-gc non-call + /// arguments. + unsigned getNumVMSArgsIdx() const { + return getVarIdx() + 3; + } + + /// Returns the number of non-gc non-call arguments attached to the + /// statepoint. Note that this is the number of arguments, not the number of + /// operands required to represent those arguments. + unsigned getNumVMSArgs() const { + return MI->getOperand(getNumVMSArgsIdx()).getImm(); + } + + /// Returns the target of the underlying call. + const MachineOperand &getCallTarget() const { + return MI->getOperand(CallTargetPos); + } + +private: + const MachineInstr *MI; +}; + class StackMaps { public: struct Location { @@ -132,6 +178,9 @@ public: /// \brief Generate a stackmap record for a patchpoint instruction. void recordPatchPoint(const MachineInstr &MI); + /// \brief Generate a stackmap record for a statepoint instruction. + void recordStatepoint(const MachineInstr &MI); + /// If there is any stack map data, create a stack map section and serialize /// the map info into it. This clears the stack map data structures /// afterwards. @@ -139,7 +188,6 @@ public: private: static const char *WSMP; - typedef SmallVector LocationVec; typedef SmallVector LiveOutVec; typedef MapVector ConstantPool; diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 87f1401..348c634 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -36,6 +36,8 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { bool UseInitArray; public: + TargetLoweringObjectFileELF() : UseInitArray(false) {} + virtual ~TargetLoweringObjectFileELF() {} void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, @@ -54,6 +56,13 @@ public: SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const override; + const MCSection * + getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; + + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; + /// Return an MCExpr to use for a reference to the specified type info global /// variable from exception handling information. const MCExpr * @@ -89,8 +98,6 @@ public: ArrayRef ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - bool isSectionAtomizableBySymbols(const MCSection &Section) const override; - const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index b5fa0e8..756262f 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -98,3 +98,6 @@ def iAny : ValueType<0 , 254>; // Pseudo valuetype mapped to the current pointer size. def iPTR : ValueType<0 , 255>; + +// Pseudo valuetype to represent "any type of any size". +def Any : ValueType<0 , 256>; diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index eceb875..d7e9209 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -63,8 +63,8 @@ namespace llvm { /// createSpillSlot - Allocate a spill slot for RC from MFI. unsigned createSpillSlot(const TargetRegisterClass *RC); - VirtRegMap(const VirtRegMap&) LLVM_DELETED_FUNCTION; - void operator=(const VirtRegMap&) LLVM_DELETED_FUNCTION; + VirtRegMap(const VirtRegMap&) = delete; + void operator=(const VirtRegMap&) = delete; public: static char ID; -- cgit v1.1