aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/CodeGen
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2015-03-23 12:10:34 -0700
committerStephen Hines <srhines@google.com>2015-03-23 12:10:34 -0700
commitebe69fe11e48d322045d5949c83283927a0d790b (patch)
treec92f1907a6b8006628a4b01615f38264d29834ea /include/llvm/CodeGen
parentb7d2e72b02a4cb8034f32f8247a2558d2434e121 (diff)
downloadexternal_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.zip
external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.gz
external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.bz2
Update aosp/master LLVM for rebase to r230699.
Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9
Diffstat (limited to 'include/llvm/CodeGen')
-rw-r--r--include/llvm/CodeGen/Analysis.h17
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h54
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h723
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h63
-rw-r--r--include/llvm/CodeGen/CommandFlags.h5
-rw-r--r--include/llvm/CodeGen/DIE.h587
-rw-r--r--include/llvm/CodeGen/FastISel.h11
-rw-r--r--include/llvm/CodeGen/ForwardControlFlowIntegrity.h1
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h16
-rw-r--r--include/llvm/CodeGen/GCMetadata.h295
-rw-r--r--include/llvm/CodeGen/GCMetadataPrinter.h76
-rw-r--r--include/llvm/CodeGen/GCStrategy.h254
-rw-r--r--include/llvm/CodeGen/GCs.h32
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h23
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h18
-rw-r--r--include/llvm/CodeGen/LinkAllCodegenComponents.h1
-rw-r--r--include/llvm/CodeGen/LiveInterval.h226
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h57
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h14
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h4
-rw-r--r--include/llvm/CodeGen/MachineDominanceFrontier.h4
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineFunction.h22
-rw-r--r--include/llvm/CodeGen/MachineInstr.h25
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h37
-rw-r--r--include/llvm/CodeGen/MachinePassRegistry.h7
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h19
-rw-r--r--include/llvm/CodeGen/MachineSSAUpdater.h4
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h1
-rw-r--r--include/llvm/CodeGen/MachineValueType.h64
-rw-r--r--include/llvm/CodeGen/PBQP/Graph.h73
-rw-r--r--include/llvm/CodeGen/PBQP/ReductionRules.h32
-rw-r--r--include/llvm/CodeGen/Passes.h86
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h132
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h6
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h14
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h2
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h127
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h2
-rw-r--r--include/llvm/CodeGen/StackMaps.h50
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h11
-rw-r--r--include/llvm/CodeGen/ValueTypes.td3
-rw-r--r--include/llvm/CodeGen/VirtRegMap.h4
44 files changed, 2605 insertions, 605 deletions
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<const GlobalVariable *, unsigned> GOTEquivUsePair;
+ DenseMap<const MCSymbol *, GOTEquivUsePair> 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<MCStreamer> 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<unsigned> 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 <typename T>
+class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
+private:
+ typedef TargetTransformInfoImplCRTPBase<T> 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<T *>(this)
+ ->getVectorInstrCost(Instruction::InsertElement, Ty, i);
+ if (Extract)
+ Cost += static_cast<T *>(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<T *>(this)
+ ->getVectorInstrCost(Instruction::InsertElement, Ty, i);
+ Cost += static_cast<T *>(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<const T *>(this)->getST();
+ }
+
+ /// \brief Local query method delegates up to T which *must* implement this!
+ const TargetLoweringBase *getTLI() const {
+ return static_cast<const T *>(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<const BaseT &>(Arg)) {}
+ BasicTTIImplBase(BasicTTIImplBase &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
+ BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ return *this;
+ }
+ BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(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<const Value *> Arguments) {
+ return BaseT::getIntrinsicCost(IID, RetTy, Arguments);
+ }
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> 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<CallInst>(J) || isa<InvokeInst>(J)) {
+ ImmutableCallSite CS(J);
+ if (const Function *F = CS.getCalledFunction()) {
+ if (!static_cast<T *>(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<unsigned, MVT> 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<T *>(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<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(Src);
+ std::pair<unsigned, MVT> 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<T *>(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<unsigned, MVT> 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<T *>(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<unsigned, MVT> 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<unsigned, MVT> 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<Type *> 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<T *>(this)
+ ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0);
+ case Intrinsic::masked_load:
+ return static_cast<T *>(this)
+ ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
+ }
+
+ const TargetLoweringBase *TLI = getTLI();
+ std::pair<unsigned, MVT> 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<T *>(this)
+ ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) +
+ static_cast<T *>(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<T *>(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<unsigned, MVT> 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<T *>(this)->getArithmeticInstrCost(Opcode, Ty);
+ // Assume the pairwise shuffles add a cost.
+ unsigned ShuffleCost =
+ NumReduxLevels * (IsPairwise + 1) *
+ static_cast<T *>(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<BasicTTIImpl> {
+ typedef BasicTTIImplBase<BasicTTIImpl> BaseT;
+ friend class BasicTTIImplBase<BasicTTIImpl>;
+
+ 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<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {}
+ BasicTTIImpl(BasicTTIImpl &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
+ TLI(std::move(Arg.TLI)) {}
+ BasicTTIImpl &operator=(const BasicTTIImpl &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ ST = RHS.ST;
+ TLI = RHS.TLI;
+ return *this;
+ }
+ BasicTTIImpl &operator=(BasicTTIImpl &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(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<MCPhysReg> 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<MCPhysReg> 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<uint16_t> 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<MCPhysReg> 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<MCPhysReg> 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<MCPhysReg> &Regs, MVT VT,
+ CCAssignFn Fn);
+
+ /// Compute the set of registers that need to be preserved and forwarded to
+ /// any musttail calls.
+ void analyzeMustTailForwardedRegisters(
+ SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> 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<bool> UniqueSectionNames("unique-section-names",
+ cl::desc("Give unique names to every section"),
+ cl::init(true));
+
cl::opt<llvm::JumpTable::JumpTableType>
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 <vector>
+
+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<DIEAbbrevData, 12> 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<DIEAbbrevData> &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<DIE> because pointer validity is requirent for the
+ // Parent pointer and DIEEntry.
+ // It can't be a list<DIE> 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<std::unique_ptr<DIE>> Children;
+
+ DIE *Parent;
+
+ /// Attribute values.
+ ///
+ SmallVector<DIEValue *, 12> 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<std::unique_ptr<DIE>> &getChildren() const {
+ return Children;
+ }
+ const SmallVectorImpl<DIEValue *> &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<DIE> 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<Value *, 16> OutVals;
SmallVector<ISD::ArgFlagsTy, 16> OutFlags;
SmallVector<unsigned, 16> 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 <string>
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<unsigned, unsigned> 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<unsigned, 50> 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 <memory>
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<GCPoint>::iterator iterator;
+ typedef std::vector<GCRoot>::iterator roots_iterator;
+ typedef std::vector<GCRoot>::const_iterator live_iterator;
+
+private:
+ const Function &F;
+ GCStrategy &S;
+ uint64_t FrameSize;
+ std::vector<GCRoot> Roots;
+ std::vector<GCPoint> 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<GCPoint>::iterator iterator;
- typedef std::vector<GCRoot>::iterator roots_iterator;
- typedef std::vector<GCRoot>::const_iterator live_iterator;
-
- private:
- const Function &F;
- GCStrategy &S;
- uint64_t FrameSize;
- std::vector<GCRoot> Roots;
- std::vector<GCPoint> 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<GCStrategy*> strategy_map_type;
- typedef std::vector<std::unique_ptr<GCStrategy>> list_type;
- typedef DenseMap<const Function*,GCFunctionInfo*> 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<std::unique_ptr<GCStrategy>, 1> GCStrategyList;
+ /// A helper map to speedup lookups into the above list
+ StringMap<GCStrategy*> 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<std::unique_ptr<GCFunctionInfo>> 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<const Function *, GCFunctionInfo *> finfo_map_type;
+ finfo_map_type FInfoMap;
+
+public:
+ typedef SmallVector<std::unique_ptr<GCStrategy>,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<GCMetadataPrinter> 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<GCMetadataPrinter> 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 <string>
namespace llvm {
-
- class GCStrategy;
-
- /// The GC strategy registry uses all the defaults from Registry.
- ///
- typedef Registry<GCStrategy> 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<std::unique_ptr<GCFunctionInfo>> 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<bool> 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<CustomGC> 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<GCStrategy> 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 <utility>
#include <unordered_map>
+#include <utility>
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<const MDNode> Desc; // Debug info descriptor.
- AssertingVH<const MDNode> 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<LexicalScope *, 4> 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 <cassert>
#include <climits>
+#include <set>
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<Segment> 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<typename T>
+ class SingleLinkedListIterator {
+ T *P;
+ public:
+ SingleLinkedListIterator<T>(T *P) : P(P) {}
+ SingleLinkedListIterator<T> &operator++() {
+ P = P->Next;
+ return *this;
+ }
+ SingleLinkedListIterator<T> &operator++(int) {
+ SingleLinkedListIterator res = *this;
+ ++*this;
+ return res;
+ }
+ bool operator!=(const SingleLinkedListIterator<T> &Other) {
+ return P != Other.operator->();
+ }
+ bool operator==(const SingleLinkedListIterator<T> &Other) {
+ return P == Other.operator->();
+ }
+ T &operator*() const {
+ return *P;
+ }
+ T *operator->() const {
+ return P;
+ }
+ };
+
+ typedef SingleLinkedListIterator<SubRange> subrange_iterator;
+ subrange_iterator subrange_begin() {
+ return subrange_iterator(SubRanges);
+ }
+ subrange_iterator subrange_end() {
+ return subrange_iterator(nullptr);
+ }
+
+ typedef SingleLinkedListIterator<const SubRange> 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<subrange_iterator> subranges() {
+ return make_range(subrange_begin(), subrange_end());
+ }
+
+ iterator_range<const_subrange_iterator> 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 <cmath>
#include <iterator>
namespace llvm {
+extern cl::opt<bool> UseSegmentSetForPhysRegs;
+
class AliasAnalysis;
class BitVector;
class BlockFrequency;
@@ -154,16 +157,11 @@ namespace llvm {
bool shrinkToUses(LiveInterval *li,
SmallVectorImpl<MachineInstr*> *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<MachineInstr*> *dead);
+ /// Specialized version of
+ /// shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *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<SlotIndex> 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<SlotIndex> *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<MachineInstr*> *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<unsigned> 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<MachineBasicBlock>::iterator iterator;
typedef DominanceFrontierBase<MachineBasicBlock>::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<typename Ty>
+ static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) {
+ return new (Allocator.Allocate<Ty>()) 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<typename STC> const STC &getSubtarget() const {
+ return *static_cast<const STC *>(STI);
+ }
+
/// getRegInfo - Return information about the registers currently in use.
///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
@@ -239,7 +255,7 @@ public:
template<typename Ty>
Ty *getInfo() {
if (!MFInfo)
- MFInfo = new (Allocator.Allocate<Ty>()) Ty(*this);
+ MFInfo = Ty::template create<Ty>(Allocator, *this);
return static_cast<Ty*>(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<MachineInstr>;
@@ -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<MachineBasicBlock, MachineLoop> LI;
friend class LoopBase<MachineBasicBlock, MachineLoop>;
- 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<MCSymbol*, 1> BeginLabels; // Labels prior to invoke.
SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke.
+ SmallVector<MCSymbol*, 1> ClauseLabels; // Labels for each clause.
MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
const Function *Personality; // Personality function.
std::vector<int> 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<MDNode> Var;
- TrackingVH<MDNode> 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<VariableDbgInfo, 4> 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 RegistryClass>
class RegisterPassParser : public MachinePassRegistryListener,
public cl::parser<typename RegistryClass::FunctionPassCtor> {
public:
- RegisterPassParser() {}
+ RegisterPassParser(cl::Option &O)
+ : cl::parser<typename RegistryClass::FunctionPassCtor>(O) {}
~RegisterPassParser() { RegistryClass::setListener(nullptr); }
- void initialize(cl::Option &O) {
- cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O);
+ void initialize() {
+ cl::parser<typename RegistryClass::FunctionPassCtor>::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<std::pair<unsigned, unsigned> > 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 <memory>
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_iterator> 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 <typename OtherMatrixT>
- 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 <typename OStream>
- 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 <typename OStream>
- 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 <typename VectorT>
+ 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<PBQP::PBQPNum>::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<MyStrategy>(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<unsigned[]> 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<RegAllocSolverImpl> 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<const SDNode*, SmallVector<SDDbgValue*, 2> > 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<SDNode *> &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<SDValue> 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:
+/// <num call arguments>, <call target>, [call arguments],
+/// <StackMaps::ConstantOp>, <flags>,
+/// <StackMaps::ConstantOp>, <num other args>, [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<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
typedef MapVector<uint64_t, uint64_t> 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<Module::ModuleFlagEntry> 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;