diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
commit | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch) | |
tree | 5343938942df402b49ec7300a1c25a2d4ccd5821 /include/llvm/CodeGen | |
parent | 31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff) |
Diffstat (limited to 'include/llvm/CodeGen')
68 files changed, 2614 insertions, 1556 deletions
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index f20185c4499a..ba88f1f78fb8 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -123,13 +123,6 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I, const ReturnInst *Ret, const TargetLoweringBase &TLI); -// True if GV can be left out of the object symbol table. This is the case -// for linkonce_odr values whose address is not significant. While legal, it is -// not normally profitable to omit them from the .o symbol table. Using this -// analysis makes sense when the information can be passed down to the linker -// or we are in LTO. -bool canBeOmittedFromSymbolTable(const GlobalValue *GV); - DenseMap<const MachineBasicBlock *, int> getFuncletMembership(const MachineFunction &MF); diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 4daca0347b77..fb8c8408fc77 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework --------*- C++ -*-===// +//===- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,35 +17,43 @@ #define LLVM_CODEGEN_ASMPRINTER_H #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/DwarfStringPoolEntry.h" +#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/InlineAsm.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" +#include <cstdint> +#include <memory> +#include <utility> +#include <vector> namespace llvm { + class AsmPrinterHandler; class BlockAddress; -class ByteStreamer; -class GCStrategy; class Constant; class ConstantArray; +class DataLayout; class DIE; class DIEAbbrev; +class DwarfDebug; class GCMetadataPrinter; class GlobalIndirectSymbol; class GlobalValue; class GlobalVariable; +class GCStrategy; class MachineBasicBlock; +class MachineConstantPoolValue; class MachineFunction; class MachineInstr; -class MachineLocation; -class MachineLoopInfo; -class MachineLoop; -class MachineConstantPoolValue; class MachineJumpTableInfo; +class MachineLoopInfo; class MachineModuleInfo; +class MachineOptimizationRemarkEmitter; class MCAsmInfo; class MCCFIInstruction; class MCContext; @@ -57,10 +65,7 @@ class MCSubtargetInfo; class MCSymbol; class MCTargetOptions; class MDNode; -class DwarfDebug; -class Mangler; class TargetLoweringObjectFile; -class DataLayout; class TargetMachine; /// This class is intended to be used as a driving class for all asm writers. @@ -84,33 +89,39 @@ public: std::unique_ptr<MCStreamer> OutStreamer; /// The current machine function. - const MachineFunction *MF; + const MachineFunction *MF = nullptr; /// This is a pointer to the current MachineModuleInfo. - MachineModuleInfo *MMI; + MachineModuleInfo *MMI = nullptr; + + /// Optimization remark emitter. + MachineOptimizationRemarkEmitter *ORE; /// The symbol for the current function. This is recalculated at the beginning /// of each call to runOnMachineFunction(). /// - MCSymbol *CurrentFnSym; + MCSymbol *CurrentFnSym = nullptr; /// The symbol used to represent the start of the current function for the /// purpose of calculating its size (e.g. using the .size directive). By /// default, this is equal to CurrentFnSym. - MCSymbol *CurrentFnSymForSize; + MCSymbol *CurrentFnSymForSize = nullptr; /// 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; MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs; + /// Enable print [latency:throughput] in output + bool EnablePrintSchedInfo = false; + private: - MCSymbol *CurrentFnBegin; - MCSymbol *CurrentFnEnd; - MCSymbol *CurExceptionSym; + MCSymbol *CurrentFnBegin = nullptr; + MCSymbol *CurrentFnEnd = nullptr; + MCSymbol *CurExceptionSym = nullptr; // The garbage collection metadata printer table. - void *GCMetadataPrinters; // Really a DenseMap. + void *GCMetadataPrinters = nullptr; // Really a DenseMap. /// Emit comments in assembly output if this is true. /// @@ -118,7 +129,7 @@ private: static char ID; /// If VerboseAsm is set, a pointer to the loop info for this function. - MachineLoopInfo *LI; + MachineLoopInfo *LI = nullptr; struct HandlerInfo { AsmPrinterHandler *Handler; @@ -126,6 +137,7 @@ private: const char *TimerDescription; const char *TimerGroupName; const char *TimerGroupDescription; + HandlerInfo(AsmPrinterHandler *Handler, const char *TimerName, const char *TimerDescription, const char *TimerGroupName, const char *TimerGroupDescription) @@ -137,11 +149,24 @@ private: /// maintains ownership of the emitters. SmallVector<HandlerInfo, 1> Handlers; +public: + struct SrcMgrDiagInfo { + SourceMgr SrcMgr; + std::vector<const MDNode *> LocInfos; + LLVMContext::InlineAsmDiagHandlerTy DiagHandler; + void *DiagContext; + }; + +private: + /// Structure for generating diagnostics for inline assembly. Only initialised + /// when necessary. + mutable std::unique_ptr<SrcMgrDiagInfo> DiagInfo; + /// If the target supports dwarf debug info, this pointer is non-null. - DwarfDebug *DD; + DwarfDebug *DD = nullptr; /// If the current module uses dwarf CFI annotations strictly for debugging. - bool isCFIMoveForDebugging; + bool isCFIMoveForDebugging = false; protected: explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); @@ -200,6 +225,7 @@ public: FUNCTION_ENTER = 0, FUNCTION_EXIT = 1, TAIL_CALL = 2, + LOG_ARGS_ENTER = 3, }; // The table will contain these structs that point to the sled, the function @@ -381,7 +407,7 @@ public: //===------------------------------------------------------------------===// // Symbol Lowering Routines. //===------------------------------------------------------------------===// -public: + MCSymbol *createTempSymbol(const Twine &Name) const; /// Return the MCSymbol for a private symbol with global value name as its @@ -407,7 +433,7 @@ public: //===------------------------------------------------------------------===// // Emission Helper Routines. //===------------------------------------------------------------------===// -public: + /// This is just convenient handler for printing offsets. void printOffset(int64_t Offset, raw_ostream &OS) const; @@ -484,7 +510,7 @@ public: /// /// \p Value - The value to emit. /// \p Size - The size of the integer (in bytes) to emit. - virtual void EmitDebugValue(const MCExpr *Value, unsigned Size) const; + virtual void EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines @@ -511,7 +537,7 @@ public: //===------------------------------------------------------------------===// // Inline Asm Support //===------------------------------------------------------------------===// -public: + // These are hooks that targets can override to implement inline asm // support. These should probably be moved out of AsmPrinter someday. @@ -555,9 +581,9 @@ public: private: /// Private state for PrintSpecial() // Assign a unique ID to this machine instruction. - mutable const MachineInstr *LastMI; - mutable unsigned LastFn; - mutable unsigned Counter; + mutable const MachineInstr *LastMI = nullptr; + mutable unsigned LastFn = 0; + mutable unsigned Counter = ~0U; /// This method emits the header for the current function. virtual void EmitFunctionHeader(); @@ -596,6 +622,7 @@ private: void emitGlobalIndirectSymbol(Module &M, const GlobalIndirectSymbol& GIS); }; -} -#endif +} // end namespace llvm + +#endif // LLVM_CODEGEN_ASMPRINTER_H diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index 7efdbcccdef5..e30e947f787f 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -42,24 +42,6 @@ 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 a cost of shuffle as a sequence of extract and insert /// operations. unsigned getPermuteShuffleOverhead(Type *Ty) { @@ -111,6 +93,11 @@ public: bool isSourceOfDivergence(const Value *V) { return false; } + unsigned getFlatAddressSpace() { + // Return an invalid address space. + return -1; + } + bool isLegalAddImmediate(int64_t imm) { return getTLI()->isLegalAddImmediate(imm); } @@ -301,6 +288,67 @@ public: unsigned getRegisterBitWidth(bool Vector) { return 32; } + /// 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 overhead of scalarizing an instructions unique + /// non-constant operands. The types of the arguments are ordinarily + /// scalar, in which case the costs are multiplied with VF. + unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args, + unsigned VF) { + unsigned Cost = 0; + SmallPtrSet<const Value*, 4> UniqueOperands; + for (const Value *A : Args) { + if (!isa<Constant>(A) && UniqueOperands.insert(A).second) { + Type *VecTy = nullptr; + if (A->getType()->isVectorTy()) { + VecTy = A->getType(); + // If A is a vector operand, VF should be 1 or correspond to A. + assert ((VF == 1 || VF == VecTy->getVectorNumElements()) && + "Vector argument does not match VF"); + } + else + VecTy = VectorType::get(A->getType(), VF); + + Cost += getScalarizationOverhead(VecTy, false, true); + } + } + + return Cost; + } + + unsigned getScalarizationOverhead(Type *VecTy, ArrayRef<const Value *> Args) { + assert (VecTy->isVectorTy()); + + unsigned Cost = 0; + + Cost += getScalarizationOverhead(VecTy, true, false); + if (!Args.empty()) + Cost += getOperandsScalarizationOverhead(Args, + VecTy->getVectorNumElements()); + else + // When no information on arguments is provided, we add the cost + // associated with one argument as a heuristic. + Cost += getScalarizationOverhead(VecTy, false, true); + + return Cost; + } + unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } unsigned getArithmeticInstrCost( @@ -341,10 +389,9 @@ public: 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; + // Return the cost of multiple scalar invocation plus the cost of + // inserting and extracting the values. + return getScalarizationOverhead(Ty, Args) + Num * Cost; } // We don't know anything about this scalar instruction. @@ -360,7 +407,8 @@ public: return 1; } - unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, + const Instruction *I = nullptr) { const TargetLoweringBase *TLI = getTLI(); int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); @@ -389,6 +437,18 @@ public: Dst->getPointerAddressSpace())) return 0; + // If this is a zext/sext of a load, return 0 if the corresponding + // extending load exists on target. + if ((Opcode == Instruction::ZExt || Opcode == Instruction::SExt) && + I && isa<LoadInst>(I->getOperand(0))) { + EVT ExtVT = EVT::getEVT(Dst); + EVT LoadVT = EVT::getEVT(Src); + unsigned LType = + ((Opcode == Instruction::ZExt) ? ISD::ZEXTLOAD : ISD::SEXTLOAD); + if (TLI->isLoadExtLegal(LType, ExtVT, LoadVT)) + 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)) @@ -446,14 +506,14 @@ public: Src->getVectorNumElements() / 2); T *TTI = static_cast<T *>(this); return TTI->getVectorSplitCost() + - (2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc)); + (2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc, I)); } // In other cases where the source or destination are illegal, assume // the operation will get scalarized. unsigned Num = Dst->getVectorNumElements(); unsigned Cost = static_cast<T *>(this)->getCastInstrCost( - Opcode, Dst->getScalarType(), Src->getScalarType()); + Opcode, Dst->getScalarType(), Src->getScalarType(), I); // Return the cost of multiple scalar invocation plus the cost of // inserting and extracting the values. @@ -487,7 +547,8 @@ public: return 0; } - unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, + const Instruction *I) { const TargetLoweringBase *TLI = getTLI(); int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); @@ -515,7 +576,7 @@ public: if (CondTy) CondTy = CondTy->getScalarType(); unsigned Cost = static_cast<T *>(this)->getCmpSelInstrCost( - Opcode, ValTy->getScalarType(), CondTy); + Opcode, ValTy->getScalarType(), CondTy, I); // Return the cost of multiple scalar invocation plus the cost of // inserting and extracting the values. @@ -534,7 +595,7 @@ public: } unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, - unsigned AddressSpace) { + unsigned AddressSpace, const Instruction *I = nullptr) { assert(!Src->isVoidTy() && "Invalid type"); std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(DL, Src); @@ -680,18 +741,42 @@ public: return Cost; } - /// Get intrinsic cost based on arguments + /// Get intrinsic cost based on arguments. unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Value *> Args, FastMathFlags FMF) { + ArrayRef<Value *> Args, FastMathFlags FMF, + unsigned VF = 1) { + unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1); + assert ((RetVF == 1 || VF == 1) && "VF > 1 and RetVF is a vector type"); + switch (IID) { default: { + // Assume that we need to scalarize this intrinsic. SmallVector<Type *, 4> Types; - for (Value *Op : Args) - Types.push_back(Op->getType()); - return static_cast<T *>(this)->getIntrinsicInstrCost(IID, RetTy, Types, - FMF); + for (Value *Op : Args) { + Type *OpTy = Op->getType(); + assert (VF == 1 || !OpTy->isVectorTy()); + Types.push_back(VF == 1 ? OpTy : VectorType::get(OpTy, VF)); + } + + if (VF > 1 && !RetTy->isVoidTy()) + RetTy = VectorType::get(RetTy, VF); + + // Compute the scalarization overhead based on Args for a vector + // intrinsic. A vectorizer will pass a scalar RetTy and VF > 1, while + // CostModel will pass a vector RetTy and VF is 1. + unsigned ScalarizationCost = UINT_MAX; + if (RetVF > 1 || VF > 1) { + ScalarizationCost = 0; + if (!RetTy->isVoidTy()) + ScalarizationCost += getScalarizationOverhead(RetTy, true, false); + ScalarizationCost += getOperandsScalarizationOverhead(Args, VF); + } + + return static_cast<T *>(this)-> + getIntrinsicInstrCost(IID, RetTy, Types, FMF, ScalarizationCost); } case Intrinsic::masked_scatter: { + assert (VF == 1 && "Can't vectorize types here."); Value *Mask = Args[3]; bool VarMask = !isa<Constant>(Mask); unsigned Alignment = cast<ConstantInt>(Args[2])->getZExtValue(); @@ -702,6 +787,7 @@ public: Alignment); } case Intrinsic::masked_gather: { + assert (VF == 1 && "Can't vectorize types here."); Value *Mask = Args[2]; bool VarMask = !isa<Constant>(Mask); unsigned Alignment = cast<ConstantInt>(Args[1])->getZExtValue(); @@ -713,19 +799,23 @@ public: } } - /// Get intrinsic cost based on argument types + /// Get intrinsic cost based on argument types. + /// If ScalarizationCostPassed is UINT_MAX, the cost of scalarizing the + /// arguments and the return value will be computed based on types. unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> Tys, FastMathFlags FMF) { + ArrayRef<Type *> Tys, FastMathFlags FMF, + unsigned ScalarizationCostPassed = UINT_MAX) { SmallVector<unsigned, 2> ISDs; unsigned SingleCallCost = 10; // Library call cost. Make it expensive. switch (IID) { default: { // Assume that we need to scalarize this intrinsic. - unsigned ScalarizationCost = 0; + unsigned ScalarizationCost = ScalarizationCostPassed; unsigned ScalarCalls = 1; Type *ScalarRetTy = RetTy; if (RetTy->isVectorTy()) { - ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + if (ScalarizationCostPassed == UINT_MAX) + ScalarizationCost = getScalarizationOverhead(RetTy, true, false); ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); ScalarRetTy = RetTy->getScalarType(); } @@ -733,7 +823,8 @@ public: for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { Type *Ty = Tys[i]; if (Ty->isVectorTy()) { - ScalarizationCost += getScalarizationOverhead(Ty, false, true); + if (ScalarizationCostPassed == UINT_MAX) + ScalarizationCost += getScalarizationOverhead(Ty, false, true); ScalarCalls = std::max(ScalarCalls, Ty->getVectorNumElements()); Ty = Ty->getScalarType(); } @@ -881,7 +972,8 @@ public: // this will emit a costly libcall, adding call overhead and spills. Make it // very expensive. if (RetTy->isVectorTy()) { - unsigned ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + unsigned ScalarizationCost = ((ScalarizationCostPassed != UINT_MAX) ? + ScalarizationCostPassed : getScalarizationOverhead(RetTy, true, false)); unsigned ScalarCalls = RetTy->getVectorNumElements(); SmallVector<Type *, 4> ScalarTys; for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { @@ -894,7 +986,8 @@ public: IID, RetTy->getScalarType(), ScalarTys, FMF); for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { if (Tys[i]->isVectorTy()) { - ScalarizationCost += getScalarizationOverhead(Tys[i], false, true); + if (ScalarizationCostPassed == UINT_MAX) + ScalarizationCost += getScalarizationOverhead(Tys[i], false, true); ScalarCalls = std::max(ScalarCalls, Tys[i]->getVectorNumElements()); } } diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index bfbd22823eb8..50e464ebb9b8 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -183,11 +183,6 @@ typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, ISD::ArgFlagsTy &ArgFlags, CCState &State); -/// ParmContext - This enum tracks whether calling convention lowering is in -/// the context of prologue or call generation. Not all backends make use of -/// this information. -typedef enum { Unknown, Prologue, Call } ParmContext; - /// CCState - This class holds information needed while lowering arguments and /// return values. It captures which registers are already assigned and which /// stack slots are used. It provides accessors to allocate these values. @@ -256,9 +251,6 @@ private: // during argument analysis. unsigned InRegsParamsProcessed; -protected: - ParmContext CallOrPrologue; - public: CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, SmallVectorImpl<CCValAssign> &locs, LLVMContext &C); @@ -510,8 +502,6 @@ public: InRegsParamsProcessed = 0; } - ParmContext getCallOrPrologue() const { return CallOrPrologue; } - // Get list of pending assignments SmallVectorImpl<llvm::CCValAssign> &getPendingLocs() { return PendingLocs; diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index aab522d00de7..317a5d3f54c8 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -119,11 +119,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), "Emit nothing, for performance testing"))); cl::opt<bool> -EnableFPMAD("enable-fp-mad", - cl::desc("Enable less precise MAD instructions to be generated"), - cl::init(false)); - -cl::opt<bool> DisableFPElim("disable-fp-elim", cl::desc("Disable frame pointer elimination optimization"), cl::init(false)); @@ -144,6 +139,12 @@ EnableNoNaNsFPMath("enable-no-nans-fp-math", cl::init(false)); cl::opt<bool> +EnableNoSignedZerosFPMath("enable-no-signed-zeros-fp-math", + cl::desc("Enable FP math optimizations that assume " + "the sign of 0 is insignificant"), + cl::init(false)); + +cl::opt<bool> EnableNoTrappingFPMath("enable-no-trapping-fp-math", cl::desc("Enable setting the FP exceptions build " "attribute not to use exceptions"), @@ -277,11 +278,11 @@ DebuggerTuningOpt("debugger-tune", // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { TargetOptions Options; - Options.LessPreciseFPMADOption = EnableFPMAD; Options.AllowFPOpFusion = FuseFPOps; Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath; + Options.NoSignedZerosFPMath = EnableNoSignedZerosFPMath; Options.NoTrappingFPMath = EnableNoTrappingFPMath; Options.FPDenormalMode = DenormalMode; Options.HonorSignDependentRoundingFPMathOption = @@ -345,28 +346,28 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features, Module &M) { for (auto &F : M) { auto &Ctx = F.getContext(); - AttributeSet Attrs = F.getAttributes(), NewAttrs; + AttributeList Attrs = F.getAttributes(), NewAttrs; if (!CPU.empty()) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, "target-cpu", CPU); if (!Features.empty()) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, "target-features", Features); if (DisableFPElim.getNumOccurrences() > 0) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, "no-frame-pointer-elim", DisableFPElim ? "true" : "false"); if (DisableTailCalls.getNumOccurrences() > 0) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, "disable-tail-calls", toStringRef(DisableTailCalls)); if (StackRealign) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, "stackrealign"); if (TrapFuncName.getNumOccurrences() > 0) @@ -376,12 +377,12 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features, if (const auto *F = Call->getCalledFunction()) if (F->getIntrinsicID() == Intrinsic::debugtrap || F->getIntrinsicID() == Intrinsic::trap) - Call->addAttribute(llvm::AttributeSet::FunctionIndex, - Attribute::get(Ctx, "trap-func-name", - TrapFuncName)); + Call->addAttribute( + llvm::AttributeList::FunctionIndex, + Attribute::get(Ctx, "trap-func-name", TrapFuncName)); // Let NewAttrs override Attrs. - NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs); + NewAttrs = Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs); F.setAttributes(NewAttrs); } } diff --git a/include/llvm/CodeGen/ExecutionDepsFix.h b/include/llvm/CodeGen/ExecutionDepsFix.h new file mode 100644 index 000000000000..1d5b9684e105 --- /dev/null +++ b/include/llvm/CodeGen/ExecutionDepsFix.h @@ -0,0 +1,220 @@ +//===- llvm/CodeGen/ExecutionDepsFix.h - Execution Dependency Fix -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file Execution Dependency Fix pass. +/// +/// Some X86 SSE instructions like mov, and, or, xor are available in different +/// variants for different operand types. These variant instructions are +/// equivalent, but on Nehalem and newer cpus there is extra latency +/// transferring data between integer and floating point domains. ARM cores +/// have similar issues when they are configured with both VFP and NEON +/// pipelines. +/// +/// This pass changes the variant instructions to minimize domain crossings. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_EXECUTIONDEPSFIX_H +#define LLVM_CODEGEN_EXECUTIONDEPSFIX_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/RegisterClassInfo.h" +#include "llvm/Support/Allocator.h" +#include <vector> + +namespace llvm { + +/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track +/// of execution domains. +/// +/// An open DomainValue represents a set of instructions that can still switch +/// execution domain. Multiple registers may refer to the same open +/// DomainValue - they will eventually be collapsed to the same execution +/// domain. +/// +/// A collapsed DomainValue represents a single register that has been forced +/// into one of more execution domains. There is a separate collapsed +/// DomainValue for each register, but it may contain multiple execution +/// domains. A register value is initially created in a single execution +/// domain, but if we were forced to pay the penalty of a domain crossing, we +/// keep track of the fact that the register is now available in multiple +/// domains. +struct DomainValue { + // Basic reference counting. + unsigned Refs; + + // Bitmask of available domains. For an open DomainValue, it is the still + // possible domains for collapsing. For a collapsed DomainValue it is the + // domains where the register is available for free. + unsigned AvailableDomains; + + // Pointer to the next DomainValue in a chain. When two DomainValues are + // merged, Victim.Next is set to point to Victor, so old DomainValue + // references can be updated by following the chain. + DomainValue *Next; + + // Twiddleable instructions using or defining these registers. + SmallVector<MachineInstr*, 8> Instrs; + + // A collapsed DomainValue has no instructions to twiddle - it simply keeps + // track of the domains where the registers are already available. + bool isCollapsed() const { return Instrs.empty(); } + + // Is domain available? + bool hasDomain(unsigned domain) const { + assert(domain < + static_cast<unsigned>(std::numeric_limits<unsigned>::digits) && + "undefined behavior"); + return AvailableDomains & (1u << domain); + } + + // Mark domain as available. + void addDomain(unsigned domain) { + AvailableDomains |= 1u << domain; + } + + // Restrict to a single domain available. + void setSingleDomain(unsigned domain) { + AvailableDomains = 1u << domain; + } + + // Return bitmask of domains that are available and in mask. + unsigned getCommonDomains(unsigned mask) const { + return AvailableDomains & mask; + } + + // First domain available. + unsigned getFirstDomain() const { + return countTrailingZeros(AvailableDomains); + } + + DomainValue() : Refs(0) { clear(); } + + // Clear this DomainValue and point to next which has all its data. + void clear() { + AvailableDomains = 0; + Next = nullptr; + Instrs.clear(); + } +}; + +/// Information about a live register. +struct LiveReg { + /// Value currently in this register, or NULL when no value is being tracked. + /// This counts as a DomainValue reference. + DomainValue *Value; + + /// Instruction that defined this register, relative to the beginning of the + /// current basic block. When a LiveReg is used to represent a live-out + /// register, this value is relative to the end of the basic block, so it + /// will be a negative number. + int Def; +}; + +class ExecutionDepsFix : public MachineFunctionPass { + SpecificBumpPtrAllocator<DomainValue> Allocator; + SmallVector<DomainValue*,16> Avail; + + const TargetRegisterClass *const RC; + MachineFunction *MF; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + RegisterClassInfo RegClassInfo; + std::vector<SmallVector<int, 1>> AliasMap; + const unsigned NumRegs; + LiveReg *LiveRegs; + struct MBBInfo { + // Keeps clearance and domain information for all registers. Note that this + // is different from the usual definition notion of liveness. The CPU + // doesn't care whether or not we consider a register killed. + LiveReg *OutRegs; + + // Whether we have gotten to this block in primary processing yet. + bool PrimaryCompleted; + + // The number of predecessors for which primary processing has completed + unsigned IncomingProcessed; + + // The value of `IncomingProcessed` at the start of primary processing + unsigned PrimaryIncoming; + + // The number of predecessors for which all processing steps are done. + unsigned IncomingCompleted; + + MBBInfo() + : OutRegs(nullptr), PrimaryCompleted(false), IncomingProcessed(0), + PrimaryIncoming(0), IncomingCompleted(0) {} + }; + typedef DenseMap<MachineBasicBlock *, MBBInfo> MBBInfoMap; + MBBInfoMap MBBInfos; + + /// List of undefined register reads in this block in forward order. + std::vector<std::pair<MachineInstr*, unsigned> > UndefReads; + + /// Storage for register unit liveness. + LivePhysRegs LiveRegSet; + + /// Current instruction number. + /// The first instruction in each basic block is 0. + int CurInstr; +public: + ExecutionDepsFix(char &PassID, const TargetRegisterClass &RC) + : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {} + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + +private: + iterator_range<SmallVectorImpl<int>::const_iterator> + regIndices(unsigned Reg) const; + // DomainValue allocation. + DomainValue *alloc(int domain = -1); + DomainValue *retain(DomainValue *DV) { + if (DV) ++DV->Refs; + return DV; + } + void release(DomainValue*); + DomainValue *resolve(DomainValue*&); + + // LiveRegs manipulations. + void setLiveReg(int rx, DomainValue *DV); + void kill(int rx); + void force(int rx, unsigned domain); + void collapse(DomainValue *dv, unsigned domain); + bool merge(DomainValue *A, DomainValue *B); + + void enterBasicBlock(MachineBasicBlock*); + void leaveBasicBlock(MachineBasicBlock*); + bool isBlockDone(MachineBasicBlock *); + void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass); + bool visitInstr(MachineInstr *); + void processDefs(MachineInstr *, bool breakDependency, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); + bool pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + unsigned Pref); + bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); + void processUndefReads(MachineBasicBlock*); +}; + +} // end namepsace llvm + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index cdaea250c33b..2abe3bb11556 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -1,4 +1,4 @@ -//===-- FastISel.h - Definition of the FastISel class ---*- C++ -*---------===// +//===- FastISel.h - Definition of the FastISel class ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,10 +16,21 @@ #define LLVM_CODEGEN_FASTISEL_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Target/TargetLowering.h" +#include <algorithm> +#include <cstdint> +#include <utility> +#include <vector> namespace llvm { @@ -30,57 +41,31 @@ class MachineConstantPool; /// quickly. class FastISel { public: - struct ArgListEntry { - Value *Val; - Type *Ty; - bool IsSExt : 1; - bool IsZExt : 1; - bool IsInReg : 1; - bool IsSRet : 1; - bool IsNest : 1; - bool IsByVal : 1; - bool IsInAlloca : 1; - bool IsReturned : 1; - bool IsSwiftSelf : 1; - bool IsSwiftError : 1; - uint16_t Alignment; - - ArgListEntry() - : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false), - IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), - IsInAlloca(false), IsReturned(false), IsSwiftSelf(false), - IsSwiftError(false), Alignment(0) {} - - /// \brief Set CallLoweringInfo attribute flags based on a call instruction - /// and called function attributes. - void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); - }; - typedef std::vector<ArgListEntry> ArgListTy; - + typedef TargetLoweringBase::ArgListEntry ArgListEntry; + typedef TargetLoweringBase::ArgListTy ArgListTy; struct CallLoweringInfo { - Type *RetTy; + Type *RetTy = nullptr; bool RetSExt : 1; bool RetZExt : 1; bool IsVarArg : 1; bool IsInReg : 1; bool DoesNotReturn : 1; bool IsReturnValueUsed : 1; + bool IsPatchPoint : 1; // \brief IsTailCall Should be modified by implementations of FastLowerCall // that perform tail call conversions. - bool IsTailCall; + bool IsTailCall = false; - unsigned NumFixedArgs; - CallingConv::ID CallConv; - const Value *Callee; - MCSymbol *Symbol; + unsigned NumFixedArgs = -1; + CallingConv::ID CallConv = CallingConv::C; + const Value *Callee = nullptr; + MCSymbol *Symbol = nullptr; ArgListTy Args; - ImmutableCallSite *CS; - MachineInstr *Call; - unsigned ResultReg; - unsigned NumResultRegs; - - bool IsPatchPoint; + ImmutableCallSite *CS = nullptr; + MachineInstr *Call = nullptr; + unsigned ResultReg = 0; + unsigned NumResultRegs = 0; SmallVector<Value *, 16> OutVals; SmallVector<ISD::ArgFlagsTy, 16> OutFlags; @@ -89,11 +74,8 @@ public: SmallVector<unsigned, 4> InRegs; CallLoweringInfo() - : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), - IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), - IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), - Callee(nullptr), Symbol(nullptr), CS(nullptr), Call(nullptr), - ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} + : RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false), + DoesNotReturn(false), IsReturnValueUsed(true), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, const Value *Target, ArgListTy &&ArgsList, @@ -101,12 +83,12 @@ public: RetTy = ResultTy; Callee = Target; - IsInReg = Call.paramHasAttr(0, Attribute::InReg); + IsInReg = Call.hasRetAttr(Attribute::InReg); DoesNotReturn = Call.doesNotReturn(); IsVarArg = FuncTy->isVarArg(); IsReturnValueUsed = !Call.getInstruction()->use_empty(); - RetSExt = Call.paramHasAttr(0, Attribute::SExt); - RetZExt = Call.paramHasAttr(0, Attribute::ZExt); + RetSExt = Call.hasRetAttr(Attribute::SExt); + RetZExt = Call.hasRetAttr(Attribute::ZExt); CallConv = Call.getCallingConv(); Args = std::move(ArgsList); @@ -125,12 +107,12 @@ public: Callee = Call.getCalledValue(); Symbol = Target; - IsInReg = Call.paramHasAttr(0, Attribute::InReg); + IsInReg = Call.hasRetAttr(Attribute::InReg); DoesNotReturn = Call.doesNotReturn(); IsVarArg = FuncTy->isVarArg(); IsReturnValueUsed = !Call.getInstruction()->use_empty(); - RetSExt = Call.paramHasAttr(0, Attribute::SExt); - RetZExt = Call.paramHasAttr(0, Attribute::ZExt); + RetSExt = Call.hasRetAttr(Attribute::SExt); + RetZExt = Call.hasRetAttr(Attribute::ZExt); CallConv = Call.getCallingConv(); Args = std::move(ArgsList); @@ -510,7 +492,6 @@ protected: } } - bool lowerCall(const CallInst *I); /// \brief Select and emit code for a binary operator instruction, which has /// an opcode which directly corresponds to the given ISD opcode. @@ -567,4 +548,4 @@ private: } // end namespace llvm -#endif +#endif // LLVM_CODEGEN_FASTISEL_H diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h index 9b5a3e1ba050..0f0005b83c54 100644 --- a/include/llvm/CodeGen/FaultMaps.h +++ b/include/llvm/CodeGen/FaultMaps.h @@ -1,4 +1,4 @@ -//===------------------- FaultMaps.h - The "FaultMaps" section --*- C++ -*-===// +//===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,26 +12,31 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/Format.h" - -#include <vector> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <map> +#include <vector> namespace llvm { class AsmPrinter; class MCExpr; -class MCSymbol; -class MCStreamer; +class raw_ostream; class FaultMaps { public: - enum FaultKind { FaultingLoad = 1, FaultKindMax }; - - static const char *faultTypeToString(FaultKind); + enum FaultKind { + FaultingLoad = 1, + FaultingLoadStore, + FaultingStore, + FaultKindMax + }; explicit FaultMaps(AsmPrinter &AP); + static const char *faultTypeToString(FaultKind); + void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel); void serializeToFaultMapSection(); @@ -39,13 +44,11 @@ private: static const char *WFMP; struct FaultInfo { - FaultKind Kind; - const MCExpr *FaultingOffsetExpr; - const MCExpr *HandlerOffsetExpr; + FaultKind Kind = FaultKindMax; + const MCExpr *FaultingOffsetExpr = nullptr; + const MCExpr *HandlerOffsetExpr = nullptr; - FaultInfo() - : Kind(FaultKindMax), FaultingOffsetExpr(nullptr), - HandlerOffsetExpr(nullptr) {} + FaultInfo() = default; explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset, const MCExpr *HandlerOffset) @@ -153,11 +156,11 @@ public: static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset; - const uint8_t *P; - const uint8_t *E; + const uint8_t *P = nullptr; + const uint8_t *E = nullptr; public: - FunctionInfoAccessor() : P(nullptr), E(nullptr) {} + FunctionInfoAccessor() = default; explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E) : P(P), E(E) {} @@ -214,6 +217,6 @@ raw_ostream &operator<<(raw_ostream &OS, raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &); -} // namespace llvm +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_FAULTMAPS_H diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 3088a86a3260..5b1fafea25b5 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===// +//===- llvm/CodeGen/GCStrategy.h - Garbage collection -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -47,19 +47,20 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_GCSTRATEGY_H -#define LLVM_IR_GCSTRATEGY_H +#ifndef LLVM_CODEGEN_GCSTRATEGY_H +#define LLVM_CODEGEN_GCSTRATEGY_H +#include "llvm/ADT/None.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 Type; + namespace GC { + /// PointKind - Used to indicate whether the address of the call instruction /// or the address after the call instruction is listed in the stackmap. For /// most runtimes, PostCall safepoints are appropriate. @@ -68,7 +69,8 @@ enum PointKind { PreCall, ///< Instr is a call instruction. PostCall ///< Instr is the return address of a call. }; -} + +} // end namespace GC /// GCStrategy describes a garbage collector algorithm's code generation /// requirements, and provides overridable hooks for those needs which cannot @@ -77,24 +79,25 @@ enum PointKind { /// be immutable. class GCStrategy { private: - std::string Name; friend class GCModuleInfo; + std::string Name; + 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. + bool UseStatepoints = false; /// 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. + unsigned NeededSafePoints = 0; ///< Bitmask of required safe points. + bool CustomReadBarriers = false; ///< Default is to insert loads. + bool CustomWriteBarriers = false; ///< Default is to insert stores. + bool CustomRoots = false; ///< Default is to pass through to backend. + bool InitRoots= true; ///< If set, roots are nulled during lowering. + bool UsesMetadata = false; ///< If set, backend must emit metadata tables. public: GCStrategy(); - virtual ~GCStrategy() {} + virtual ~GCStrategy() = default; /// Return the name of the GC strategy. This is the value of the collector /// name string specified on functions which use this strategy. @@ -172,6 +175,7 @@ public: /// register your GCMetadataPrinter subclass with the /// GCMetadataPrinterRegistery as well. typedef Registry<GCStrategy> GCRegistry; -} -#endif +} // end namespace llvm + +#endif // LLVM_CODEGEN_GCSTRATEGY_H diff --git a/include/llvm/CodeGen/GlobalISel/CallLowering.h b/include/llvm/CodeGen/GlobalISel/CallLowering.h index 0b157bf937a3..3e9a9d514cb8 100644 --- a/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -35,9 +35,11 @@ public: unsigned Reg; Type *Ty; ISD::ArgFlagsTy Flags; + bool IsFixed; - ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}) - : Reg(Reg), Ty(Ty), Flags(Flags) {} + ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}, + bool IsFixed = true) + : Reg(Reg), Ty(Ty), Flags(Flags), IsFixed(IsFixed) {} }; /// Argument handling is mostly uniform between the four places that @@ -68,15 +70,34 @@ public: uint64_t Size, MachinePointerInfo &MPO, CCValAssign &VA) = 0; + /// Handle custom values, which may be passed into one or more of \p VAs. + /// \return The number of \p VAs that have been assigned after the first + /// one, and which should therefore be skipped from further + /// processing. + virtual unsigned assignCustomValue(const ArgInfo &Arg, + ArrayRef<CCValAssign> VAs) { + // This is not a pure virtual method because not all targets need to worry + // about custom values. + llvm_unreachable("Custom values not supported"); + } + unsigned extendRegister(unsigned ValReg, CCValAssign &VA); - ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) - : MIRBuilder(MIRBuilder), MRI(MRI) {} + virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, const ArgInfo &Info, + CCState &State) { + return AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State); + } + + ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + CCAssignFn *AssignFn) + : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {} virtual ~ValueHandler() {} MachineIRBuilder &MIRBuilder; MachineRegisterInfo &MRI; + CCAssignFn *AssignFn; }; protected: @@ -96,12 +117,12 @@ protected: void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; - /// Invoke the \p AssignFn on each of the given \p Args and then use + /// Invoke Handler::assignArg on each of the given \p Args and then use /// \p Callback to move them to the assigned locations. /// /// \return True if everything has succeeded, false otherwise. - bool handleAssignments(MachineIRBuilder &MIRBuilder, CCAssignFn *AssignFn, - ArrayRef<ArgInfo> Args, ValueHandler &Callback) const; + bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, + ValueHandler &Callback) const; public: CallLowering(const TargetLowering *TLI) : TLI(TLI) {} @@ -135,6 +156,8 @@ public: /// This hook must be implemented to lower the given call instruction, /// including argument and return value marshalling. /// + /// \p CallConv is the calling convention to be used for the call. + /// /// \p Callee is the destination of the call. It should be either a register, /// globaladdress, or externalsymbol. /// @@ -150,14 +173,16 @@ public: /// needs to be passed. /// /// \return true if the lowering succeeded, false otherwise. - virtual bool lowerCall(MachineIRBuilder &MIRBuilder, + virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, ArrayRef<ArgInfo> OrigArgs) const { return false; } - /// This hook must be implemented to lower the given call instruction, - /// including argument and return value marshalling. + /// Lower the given call instruction, including argument and return value + /// marshalling. + /// + /// \p CI is the call/invoke instruction. /// /// \p ResReg is a register where the call's return value should be stored (or /// 0 if there is no return value). @@ -171,9 +196,9 @@ public: /// range of an immediate jump. /// /// \return true if the lowering succeeded, false otherwise. - virtual bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI, - unsigned ResReg, ArrayRef<unsigned> ArgRegs, - std::function<unsigned()> GetCalleeReg) const; + bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, + unsigned ResReg, ArrayRef<unsigned> ArgRegs, + std::function<unsigned()> GetCalleeReg) const; }; } // End namespace llvm. diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 26ba5c67beb5..31ffdc0e2e78 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -34,6 +34,7 @@ class Instruction; class MachineBasicBlock; class MachineFunction; class MachineInstr; +class OptimizationRemarkEmitter; class MachineRegisterInfo; class TargetPassConfig; @@ -55,21 +56,20 @@ private: /// Mapping of the values of the current LLVM IR function /// to the related virtual registers. ValueToVReg ValToVReg; - // Constants are special because when we encounter one, - // we do not know at first where to insert the definition since - // this depends on all its uses. - // Thus, we will insert the sequences to materialize them when - // we know all their users. - // In the meantime, just keep it in a set. - // Note: Constants that end up as immediate in the related instructions, - // do not appear in that map. - SmallSetVector<const Constant *, 8> Constants; // N.b. it's not completely obvious that this will be sufficient for every // LLVM IR construct (with "invoke" being the obvious candidate to mess up our // lives. DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB; + // One BasicBlock can be translated to multiple MachineBasicBlocks. For such + // BasicBlocks translated to multiple MachineBasicBlocks, MachinePreds retains + // a mapping between the edges arriving at the BasicBlock to the corresponding + // created MachineBasicBlocks. Some BasicBlocks that get translated to a + // single MachineBasicBlock may also end up in this Map. + typedef std::pair<const BasicBlock *, const BasicBlock *> CFGEdge; + DenseMap<CFGEdge, SmallVector<MachineBasicBlock *, 1>> MachinePreds; + // List of stubbed PHI instructions, for values and basic blocks to be filled // in once all MachineBasicBlocks have been created. SmallVector<std::pair<const PHINode *, MachineInstr *>, 4> PendingPHIs; @@ -122,7 +122,9 @@ private: /// Translate an LLVM store instruction into generic IR. bool translateStore(const User &U, MachineIRBuilder &MIRBuilder); - bool translateMemcpy(const CallInst &CI, MachineIRBuilder &MIRBuilder); + /// Translate an LLVM string intrinsic (memcpy, memset, ...). + bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, + unsigned Intrinsic); void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder); @@ -132,6 +134,8 @@ private: bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder); + bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder); + /// Translate call instruction. /// \pre \p U is a call instruction. bool translateCall(const User &U, MachineIRBuilder &MIRBuilder); @@ -145,11 +149,6 @@ private: bool translateCast(unsigned Opcode, const User &U, MachineIRBuilder &MIRBuilder); - /// Translate static alloca instruction (i.e. one of constant size and in the - /// first basic block). - bool translateStaticAlloca(const AllocaInst &Inst, - MachineIRBuilder &MIRBuilder); - /// Translate a phi instruction. bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder); @@ -182,6 +181,8 @@ private: bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); + bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder); + bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder); bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder); @@ -190,12 +191,16 @@ private: bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder); + bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder); + /// Translate return (ret) instruction. /// The target needs to implement CallLowering::lowerReturn for /// this to succeed. /// \pre \p U is a return instruction. bool translateRet(const User &U, MachineIRBuilder &MIRBuilder); + bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder); + bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder); } @@ -227,9 +232,6 @@ private: bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder); } - bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder) { - return translateStaticAlloca(cast<AllocaInst>(U), MIRBuilder); - } bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) { return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder); } @@ -281,9 +283,6 @@ private: bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder); } - bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder) { - return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder); - } bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder); } @@ -294,11 +293,16 @@ private: return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder); } + bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder); + + bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder); + + bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder); + + bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder); + // Stubs to keep the compiler happy while we implement the rest of the // translation. - bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { return false; } @@ -335,18 +339,6 @@ private: bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } /// @} @@ -371,6 +363,9 @@ private: /// Current target configuration. Controls how the pass handles errors. const TargetPassConfig *TPC; + /// Current optimization remark emitter. Used to report failures. + std::unique_ptr<OptimizationRemarkEmitter> ORE; + // * Insert all the code needed to materialize the constants // at the proper place. E.g., Entry block or dominator block // of each constant depending on how fancy we want to be. @@ -390,10 +385,27 @@ private: /// the type being accessed (according to the Module's DataLayout). unsigned getMemOpAlignment(const Instruction &I); - /// Get the MachineBasicBlock that represents \p BB. - /// If such basic block does not exist, it is created. - MachineBasicBlock &getOrCreateBB(const BasicBlock &BB); + /// Get the MachineBasicBlock that represents \p BB. Specifically, the block + /// returned will be the head of the translated block (suitable for branch + /// destinations). + MachineBasicBlock &getMBB(const BasicBlock &BB); + + /// Record \p NewPred as a Machine predecessor to `Edge.second`, corresponding + /// to `Edge.first` at the IR level. This is used when IRTranslation creates + /// multiple MachineBasicBlocks for a given IR block and the CFG is no longer + /// represented simply by the IR-level CFG. + void addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred); + /// Returns the Machine IR predecessors for the given IR CFG edge. Usually + /// this is just the single MachineBasicBlock corresponding to the predecessor + /// in the IR. More complex lowering can result in multiple MachineBasicBlocks + /// preceding the original though (e.g. switch instructions). + SmallVector<MachineBasicBlock *, 1> getMachinePredBBs(CFGEdge Edge) { + auto RemappedEdge = MachinePreds.find(Edge); + if (RemappedEdge != MachinePreds.end()) + return RemappedEdge->second; + return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first)); + } public: // Ctor, nothing fancy. @@ -407,13 +419,13 @@ public: // CallLowering = MF.subtarget.getCallLowering() // F = MF.getParent() // MIRBuilder.reset(MF) - // MIRBuilder.getOrCreateBB(F.getEntryBB()) + // getMBB(F.getEntryBB()) // CallLowering->translateArguments(MIRBuilder, F, ValToVReg) // for each bb in F - // MIRBuilder.getOrCreateBB(bb) + // getMBB(bb) // for each inst in bb // if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence)) - // report_fatal_error(“Don’t know how to translate input"); + // report_fatal_error("Don't know how to translate input"); // finalize() bool runOnMachineFunction(MachineFunction &MF) override; }; diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 63b4f7b9507f..d8096aeb215a 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -16,8 +16,13 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H #define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H +#include "llvm/ADT/Optional.h" +#include <cstdint> + namespace llvm { class MachineInstr; +class MachineOperand; +class MachineRegisterInfo; class RegisterBankInfo; class TargetInstrInfo; class TargetRegisterInfo; @@ -56,6 +61,14 @@ protected: const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const; + + Optional<int64_t> getConstantVRegVal(unsigned VReg, + const MachineRegisterInfo &MRI) const; + + bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, + const MachineRegisterInfo &MRI) const; + + bool isObviouslySafeToFold(MachineInstr &MI) const; }; } // End namespace llvm. diff --git a/include/llvm/CodeGen/GlobalISel/Legalizer.h b/include/llvm/CodeGen/GlobalISel/Legalizer.h index 8284ab6dac65..bed7230cc013 100644 --- a/include/llvm/CodeGen/GlobalISel/Legalizer.h +++ b/include/llvm/CodeGen/GlobalISel/Legalizer.h @@ -58,6 +58,9 @@ public: bool combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII); + bool combineMerges(MachineInstr &MI, MachineRegisterInfo &MRI, + const TargetInstrInfo &TII); + bool runOnMachineFunction(MachineFunction &MF) override; }; } // End namespace llvm. diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 56c444ca46be..8fecafdc08d0 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -55,11 +55,7 @@ public: /// /// Considered as an opaque blob, the legal code will use and define the same /// registers as \p MI. - LegalizeResult legalizeInstrStep(MachineInstr &MI, - const LegalizerInfo &LegalizerInfo); - - LegalizeResult legalizeInstr(MachineInstr &MI, - const LegalizerInfo &LegalizerInfo); + LegalizeResult legalizeInstrStep(MachineInstr &MI); /// Legalize an instruction by emiting a runtime library call instead. LegalizeResult libcall(MachineInstr &MI); @@ -87,6 +83,10 @@ public: LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + /// Expose MIRBuilder so clients can set their own RecordInsertInstruction + /// functions + MachineIRBuilder MIRBuilder; + private: /// Helper function to split a wide generic register into bitwise blocks with @@ -95,8 +95,8 @@ private: void extractParts(unsigned Reg, LLT Ty, int NumParts, SmallVectorImpl<unsigned> &Ops); - MachineIRBuilder MIRBuilder; MachineRegisterInfo &MRI; + const LegalizerInfo &LI; }; } // End namespace llvm. diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index edf52daf3f8f..30d67eb49923 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -25,6 +25,7 @@ namespace llvm { class LLVMContext; class MachineInstr; +class MachineIRBuilder; class MachineRegisterInfo; class Type; class VectorType; @@ -96,6 +97,7 @@ public: }; LegalizerInfo(); + virtual ~LegalizerInfo() = default; /// Compute any ancillary tables needed to quickly decide how an operation /// should be handled. This must be called after all "set*Action"methods but @@ -144,7 +146,7 @@ public: /// Iterate the given function (typically something like doubling the width) /// on Ty until we find a legal type for this operation. LLT findLegalType(const InstrAspect &Aspect, - std::function<LLT(LLT)> NextType) const { + function_ref<LLT(LLT)> NextType) const { LegalizeAction Action; const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx]; LLT Ty = Aspect.Type; @@ -186,6 +188,10 @@ public: bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + virtual bool legalizeCustom(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const; + private: static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START; static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index ecd3e5e1e138..472f50576d96 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -108,6 +108,9 @@ public: /// Set the debug location to \p DL for all the next build instructions. void setDebugLoc(const DebugLoc &DL) { this->DL = DL; } + /// Get the current instruction's debug location. + DebugLoc getDebugLoc() { return DL; } + /// Build and insert <empty> = \p Opcode <empty>. /// The insertion point is the one set by the last call of either /// setBasicBlock or setMI. @@ -127,6 +130,29 @@ public: /// Insert an existing instruction at the insertion point. MachineInstrBuilder insertInstr(MachineInstrBuilder MIB); + /// Build and insert a DBG_VALUE instruction expressing the fact that the + /// associated \p Variable lives in \p Reg (suitably modified by \p Expr). + MachineInstrBuilder buildDirectDbgValue(unsigned Reg, const MDNode *Variable, + const MDNode *Expr); + + /// Build and insert a DBG_VALUE instruction expressing the fact that the + /// associated \p Variable lives in memory at \p Reg + \p Offset (suitably + /// modified by \p Expr). + MachineInstrBuilder buildIndirectDbgValue(unsigned Reg, unsigned Offset, + const MDNode *Variable, + const MDNode *Expr); + /// Build and insert a DBG_VALUE instruction expressing the fact that the + /// associated \p Variable lives in the stack slot specified by \p FI + /// (suitably modified by \p Expr). + MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable, + const MDNode *Expr); + + /// Build and insert a DBG_VALUE instructions specifying that \p Variable is + /// given by \p C (suitably modified by \p Expr). + MachineInstrBuilder buildConstDbgValue(const Constant &C, unsigned Offset, + const MDNode *Variable, + const MDNode *Expr); + /// Build and insert \p Res<def> = G_FRAME_INDEX \p Idx /// /// G_FRAME_INDEX materializes the address of an alloca value or other @@ -203,6 +229,22 @@ public: MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0, unsigned Op1); + /// Build and insert \p Res<def> = G_PTR_MASK \p Op0, \p NumBits + /// + /// G_PTR_MASK clears the low bits of a pointer operand without destroying its + /// pointer properties. This has the effect of rounding the address *down* to + /// a specified alignment in bits. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res and \p Op0 must be generic virtual registers with pointer + /// type. + /// \pre \p NumBits must be an integer representing the number of low bits to + /// be cleared in \p Op0. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0, + uint32_t NumBits); + /// Build and insert \p Res<def>, \p CarryOut<def> = G_UADDE \p Op0, /// \p Op1, \p CarryIn /// @@ -220,6 +262,19 @@ public: MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0, unsigned Op1, unsigned CarryIn); + /// Build and insert \p Res<def> = G_AND \p Op0, \p Op1 + /// + /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p + /// Op1. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers + /// with the same (scalar or vector) type). + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0, + unsigned Op1); + /// Build and insert \p Res<def> = G_ANYEXT \p Op0 /// /// G_ANYEXT produces a register of the specified width, with bits 0 to @@ -273,6 +328,19 @@ public: /// \return The newly created instruction. MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op); + /// Build and insert \p Res<def> = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or + /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. + /// /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar or vector type. + /// \pre \p Op must be a generic virtual register with scalar or vector type. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op); + + /// Build and insert an appropriate cast between two registers of equal size. + MachineInstrBuilder buildCast(unsigned Dst, unsigned Src); + /// Build and insert G_BR \p Dest /// /// G_BR is an unconditional branch to \p Dest. @@ -296,6 +364,16 @@ public: /// \return The newly created instruction. MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB); + /// Build and insert G_BRINDIRECT \p Tgt + /// + /// G_BRINDIRECT is an indirect branch to \p Tgt. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Tgt must be a generic virtual register with pointer type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildBrIndirect(unsigned Tgt); + /// Build and insert \p Res = G_CONSTANT \p Val /// /// G_CONSTANT is an integer constant with the specified size and value. \p @@ -362,19 +440,16 @@ public: MachineInstrBuilder buildStore(unsigned Val, unsigned Addr, MachineMemOperand &MMO); - /// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0, ...`. - /// - /// If \p Res[i] has size N bits, G_EXTRACT sets \p Res[i] to bits `[Idxs[i], - /// Idxs[i] + N)` of \p Src. + /// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0`. /// /// \pre setBasicBlock or setMI must have been called. - /// \pre Indices must be in ascending order of bit position. - /// \pre Each member of \p Results and \p Src must be a generic - /// virtual register. + /// \pre \p Res and \p Src must be generic virtual registers. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildExtract(ArrayRef<unsigned> Results, - ArrayRef<uint64_t> Indices, unsigned Src); + MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index); + + /// Build and insert \p Res = IMPLICIT_DEF. + MachineInstrBuilder buildUndef(unsigned Dst); /// Build and insert \p Res<def> = G_SEQUENCE \p Op0, \p Idx0... /// @@ -393,6 +468,31 @@ public: ArrayRef<unsigned> Ops, ArrayRef<uint64_t> Indices); + /// Build and insert \p Res<def> = G_MERGE_VALUES \p Op0, ... + /// + /// G_MERGE_VALUES combines the input elements contiguously into a larger + /// register. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre The entire register \p Res (and no more) must be covered by the input + /// registers. + /// \pre The type of all \p Ops registers must be identical. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildMerge(unsigned Res, ArrayRef<unsigned> Ops); + + /// Build and insert \p Res0<def>, ... = G_UNMERGE_VALUES \p Op + /// + /// G_UNMERGE_VALUES splits contiguous bits of the input into multiple + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre The entire register \p Res (and no more) must be covered by the input + /// registers. + /// \pre The type of all \p Res registers must be identical. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, unsigned Op); + void addUsesWithIndices(MachineInstrBuilder MIB) {} template <typename... ArgTys> @@ -411,14 +511,8 @@ public: return MIB; } - template <typename... ArgTys> MachineInstrBuilder buildInsert(unsigned Res, unsigned Src, - unsigned Op, unsigned Index, ArgTys... Args) { - MachineInstrBuilder MIB = - buildInstr(TargetOpcode::G_INSERT).addDef(Res).addUse(Src); - addUsesWithIndices(MIB, Op, Index, Args...); - return MIB; - } + unsigned Op, unsigned Index); /// Build and insert either a G_INTRINSIC (if \p HasSideEffects is false) or /// G_INTRINSIC_W_SIDE_EFFECTS instruction. Its first operand will be the @@ -500,6 +594,30 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst, unsigned Op0, unsigned Op1); + + /// Build and insert \p Res<def> = G_INSERT_VECTOR_ELT \p Val, + /// \p Elt, \p Idx + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res and \p Val must be a generic virtual register + // with the same vector type. + /// \pre \p Elt and \p Idx must be a generic virtual register + /// with scalar type. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val, + unsigned Elt, unsigned Idx); + + /// Build and insert \p Res<def> = G_EXTRACT_VECTOR_ELT \p Val, \p Idx + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar type. + /// \pre \p Val must be a generic virtual register with vector type. + /// \pre \p Idx must be a generic virtual register with scalar type. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val, + unsigned Idx); }; } // End namespace llvm. diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index b331533cd7fb..daa8dcf2061b 100644 --- a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -67,6 +67,7 @@ #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" namespace llvm { // Forward declarations. @@ -484,6 +485,9 @@ private: /// This is required for non-fast mode. MachineBranchProbabilityInfo *MBPI; + /// Current optimization remark emitter. Used to report failures. + std::unique_ptr<MachineOptimizationRemarkEmitter> MORE; + /// Helper class used for every code morphing. MachineIRBuilder MIRBuilder; diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h index b05bf9948243..5d758423f4e7 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -42,7 +42,7 @@ private: public: RegisterBank(unsigned ID, const char *Name, unsigned Size, - const uint32_t *ContainedRegClasses); + const uint32_t *ContainedRegClasses, unsigned NumRegClasses); /// Get the identifier of this register bank. unsigned getID() const { return ID; } diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 312dc9314d45..600733ac6a2d 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -317,12 +317,18 @@ public: /// The final mapping of the instruction. const InstructionMapping &getInstrMapping() const { return InstrMapping; } + + /// The MachineRegisterInfo we used to realize the mapping. + MachineRegisterInfo &getMRI() const { return MRI; } /// @} /// Create as many new virtual registers as needed for the mapping of the \p /// OpIdx-th operand. /// The number of registers is determined by the number of breakdown for the /// related operand in the instruction mapping. + /// The type of the new registers is a plain scalar of the right size. + /// The proper type is expected to be set when the mapping is applied to + /// the instruction(s) that realizes the mapping. /// /// \pre getMI().getOperand(OpIdx).isReg() /// @@ -372,15 +378,15 @@ protected: /// Keep dynamically allocated PartialMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, const PartialMapping *> MapOfPartialMappings; + mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>> MapOfPartialMappings; /// Keep dynamically allocated ValueMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, const ValueMapping *> MapOfValueMappings; + mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping> > MapOfValueMappings; /// Keep dynamically allocated array of ValueMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, ValueMapping *> MapOfOperandsMappings; + mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>> MapOfOperandsMappings; /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks /// RegisterBank instances. @@ -487,6 +493,12 @@ protected: /// Basically, that means that \p OpdMapper.getMI() is left untouched /// aside from the reassignment of the register operand that have been /// remapped. + /// + /// The type of all the new registers that have been created by the + /// mapper are properly remapped to the type of the original registers + /// they replace. In other words, the semantic of the instruction does + /// not change, only the register banks. + /// /// If the mapping of one of the operand spans several registers, this /// method will abort as this is not like a default mapping anymore. /// @@ -500,7 +512,7 @@ protected: } public: - virtual ~RegisterBankInfo(); + virtual ~RegisterBankInfo() = default; /// Get the register bank identified by \p ID. const RegisterBank &getRegBank(unsigned ID) const { diff --git a/include/llvm/CodeGen/GlobalISel/Utils.h b/include/llvm/CodeGen/GlobalISel/Utils.h index f5d5f5cdf0cd..52bf965a3cb3 100644 --- a/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/include/llvm/CodeGen/GlobalISel/Utils.h @@ -15,15 +15,21 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_UTILS_H #define LLVM_CODEGEN_GLOBALISEL_UTILS_H +#include "llvm/ADT/StringRef.h" + namespace llvm { class MachineFunction; class MachineInstr; +class MachineOptimizationRemarkEmitter; +class MachineOptimizationRemarkMissed; class MachineRegisterInfo; class MCInstrDesc; class RegisterBankInfo; class TargetInstrInfo; +class TargetPassConfig; class TargetRegisterInfo; +class Twine; /// Try to constrain Reg so that it is usable by argument OpIdx of the /// provided MCInstrDesc \p II. If this fails, create a new virtual @@ -39,5 +45,20 @@ unsigned constrainOperandRegClass(const MachineFunction &MF, MachineInstr &InsertPt, const MCInstrDesc &II, unsigned Reg, unsigned OpIdx); +/// Check whether an instruction \p MI is dead: it only defines dead virtual +/// registers, and doesn't have other side effects. +bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI); + +/// Report an ISel error as a missed optimization remark to the LLVMContext's +/// diagnostic stream. Set the FailedISel MachineFunction property. +void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, + MachineOptimizationRemarkEmitter &MORE, + MachineOptimizationRemarkMissed &R); + +void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, + MachineOptimizationRemarkEmitter &MORE, + const char *PassName, StringRef Msg, + const MachineInstr &MI); + } // End namespace llvm. #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index df700bf0c53d..ee3fd0bdda2a 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -245,6 +245,12 @@ namespace ISD { /// Simple binary floating point operators. FADD, FSUB, FMUL, FDIV, FREM, + /// Constrained versions of the binary floating point operators. + /// These will be lowered to the simple operators before final selection. + /// They are used to limit optimizations while the DAG is being + /// optimized. + STRICT_FADD, STRICT_FSUB, STRICT_FMUL, STRICT_FDIV, STRICT_FREM, + /// FMA - Perform a * b + c with no intermediate rounding step. FMA, @@ -281,7 +287,8 @@ namespace ISD { /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR /// identified by the (potentially variable) element number IDX. If the /// return type is an integer type larger than the element type of the - /// vector, the result is extended to the width of the return type. + /// vector, the result is extended to the width of the return type. In + /// that case, the high bits are undefined. EXTRACT_VECTOR_ELT, /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of @@ -332,6 +339,12 @@ namespace ISD { /// Bitwise operators - logical and, logical or, logical xor. AND, OR, XOR, + /// ABS - Determine the unsigned absolute value of a signed integer value of + /// the same bitwidth. + /// Note: A value of INT_MIN will return INT_MIN, no saturation or overflow + /// is performed. + ABS, + /// Shift and rotation operations. After legalization, the type of the /// shift amount is known to be TLI.getShiftAmountTy(). Before legalization /// the shift amount can be any type, but care must be taken to ensure it is @@ -801,10 +814,11 @@ namespace ISD { PRE_INC, PRE_DEC, POST_INC, - POST_DEC, - LAST_INDEXED_MODE + POST_DEC }; + static const int LAST_INDEXED_MODE = POST_DEC + 1; + //===--------------------------------------------------------------------===// /// LoadExtType enum - This enum defines the three variants of LOADEXT /// (load with extension). @@ -819,10 +833,11 @@ namespace ISD { NON_EXTLOAD = 0, EXTLOAD, SEXTLOAD, - ZEXTLOAD, - LAST_LOADEXT_TYPE + ZEXTLOAD }; + static const int LAST_LOADEXT_TYPE = ZEXTLOAD + 1; + NodeType getExtForLoadExtType(bool IsFP, LoadExtType); //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h new file mode 100644 index 000000000000..848ee1dc0dc6 --- /dev/null +++ b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h @@ -0,0 +1,76 @@ +///===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*--===// +/// +/// The LLVM Compiler Infrastructure +/// +/// This file is distributed under the University of Illinois Open Source +/// License. See LICENSE.TXT for details. +/// +///===---------------------------------------------------------------------===// +/// \file +/// This is an alternative analysis pass to MachineBlockFrequencyInfo. The +/// difference is that with this pass the block frequencies are not computed +/// when the analysis pass is executed but rather when the BFI result is +/// explicitly requested by the analysis client. +/// +///===---------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H +#define LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H + +#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" +#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" + +namespace llvm { +/// \brief This is an alternative analysis pass to MachineBlockFrequencyInfo. +/// The difference is that with this pass, the block frequencies are not +/// computed when the analysis pass is executed but rather when the BFI result +/// is explicitly requested by the analysis client. +/// +/// This works by checking querying if MBFI is available and otherwise +/// generating MBFI on the fly. In this case the passes required for (LI, DT) +/// are also queried before being computed on the fly. +/// +/// Note that it is expected that we wouldn't need this functionality for the +/// new PM since with the new PM, analyses are executed on demand. + +class LazyMachineBlockFrequencyInfoPass : public MachineFunctionPass { +private: + /// If generated on the fly this own the instance. + mutable std::unique_ptr<MachineBlockFrequencyInfo> OwnedMBFI; + + /// If generated on the fly this own the instance. + mutable std::unique_ptr<MachineLoopInfo> OwnedMLI; + + /// If generated on the fly this own the instance. + mutable std::unique_ptr<MachineDominatorTree> OwnedMDT; + + /// The function. + MachineFunction *MF = nullptr; + + /// \brief Calculate MBFI and all other analyses that's not available and + /// required by BFI. + MachineBlockFrequencyInfo &calculateIfNotAvailable() const; + +public: + static char ID; + + LazyMachineBlockFrequencyInfoPass(); + + /// \brief Compute and return the block frequencies. + MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); } + + /// \brief Compute and return the block frequencies. + const MachineBlockFrequencyInfo &getBFI() const { + return calculateIfNotAvailable(); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnMachineFunction(MachineFunction &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M) const override; +}; +} +#endif diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 7d7e48af2a0f..6c35832f963c 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -1,4 +1,4 @@ -//===- LexicalScopes.cpp - Collecting lexical scope info -*- C++ -*--------===// +//===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,19 +19,18 @@ #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/IR/DebugLoc.h" #include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/ValueHandle.h" +#include <cassert> #include <unordered_map> #include <utility> + namespace llvm { -class MachineInstr; class MachineBasicBlock; class MachineFunction; +class MachineInstr; //===----------------------------------------------------------------------===// /// InsnRange - This is used to track range of instructions with identical @@ -43,13 +42,15 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange; /// LexicalScope - This class is used to track scope information. /// class LexicalScope { - public: LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *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"); + : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) { + assert(D); + assert(D->getSubprogram()->getUnit()->getEmissionKind() != + DICompileUnit::NoDebug && + "Don't build lexical scopes for non-debug locations"); + assert(D->isResolved() && "Expected resolved node"); assert((!I || I->isResolved()) && "Expected resolved node"); if (Parent) Parent->addChild(this); @@ -127,10 +128,10 @@ private: // Contents not owned. SmallVector<InsnRange, 4> Ranges; - const MachineInstr *LastInsn; // Last instruction of this scope. - const MachineInstr *FirstInsn; // First instruction of this scope. - unsigned DFSIn, DFSOut; // In & Out Depth use to determine - // scope nesting. + const MachineInstr *LastInsn = nullptr; // Last instruction of this scope. + const MachineInstr *FirstInsn = nullptr; // First instruction of this scope. + unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting. + unsigned DFSOut = 0; }; //===----------------------------------------------------------------------===// @@ -139,7 +140,7 @@ private: /// class LexicalScopes { public: - LexicalScopes() : MF(nullptr), CurrentFnLexicalScope(nullptr) {} + LexicalScopes() = default; /// initialize - Scan machine function and constuct lexical scope nest, resets /// the instance if necessary. @@ -225,8 +226,7 @@ private: assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges, DenseMap<const MachineInstr *, LexicalScope *> &M); -private: - const MachineFunction *MF; + const MachineFunction *MF = nullptr; /// LexicalScopeMap - Tracks the scopes in the current function. // Use an unordered_map to ensure value pointer validity over insertion. @@ -249,9 +249,9 @@ private: /// CurrentFnLexicalScope - Top level scope for the current function. /// - LexicalScope *CurrentFnLexicalScope; + LexicalScope *CurrentFnLexicalScope = nullptr; }; -} // end llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_LEXICALSCOPES_H diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index a86706223261..b792cba4b78a 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -227,15 +227,22 @@ namespace llvm { LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) { assert(Other.segmentSet == nullptr && "Copying of LiveRanges with active SegmentSets is not supported"); + assign(Other, Allocator); + } + + /// Copies values numbers and live segments from \p Other into this range. + void assign(const LiveRange &Other, BumpPtrAllocator &Allocator) { + if (this == &Other) + return; + assert(Other.segmentSet == nullptr && + "Copying of LiveRanges with active SegmentSets is not supported"); // Duplicate valnos. - for (const VNInfo *VNI : Other.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) { + for (const Segment &S : Other.segments) segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); - } } /// advanceTo - Advance the specified iterator to point to the Segment @@ -767,6 +774,19 @@ namespace llvm { const MachineRegisterInfo &MRI, const SlotIndexes &Indexes) const; + /// Refines the subranges to support \p LaneMask. This may only be called + /// for LI.hasSubrange()==true. Subregister ranges are split or created + /// until \p LaneMask can be matched exactly. \p Mod is executed on the + /// matching subranges. + /// + /// Example: + /// Given an interval with subranges with lanemasks L0F00, L00F0 and + /// L000F, refining for mask L0018. Will split the L00F0 lane into + /// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod + /// function will be applied to the L0010 and L0008 subranges. + void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, + std::function<void(LiveInterval::SubRange&)> Mod); + bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index f8dc52566dc0..f5b1f87720ad 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// // -// This file implements the LiveInterval analysis pass. Given some numbering of -// each the machine instructions (in this implemention depth-first order) an -// interval [i, j) is said to be a live interval for register v if there is no -// instruction with number j' > j such that v is live at j' and there is no -// instruction with number i' < i such that v is live at i'. In this -// implementation intervals can have holes, i.e. an interval might look like -// [1,20), [50,65), [1000,1001). +/// \file This file implements the LiveInterval analysis pass. Given some +/// numbering of each the machine instructions (in this implemention depth-first +/// order) an interval [i, j) is said to be a live interval for register v if +/// there is no instruction with number j' > j such that v is live at j' and +/// there is no instruction with number i' < i such that v is live at i'. In +/// this implementation intervals can have holes, i.e. an interval might look +/// like [1,20), [50,65), [1000,1001). // //===----------------------------------------------------------------------===// @@ -60,20 +60,17 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; LiveRangeCalc *LRCalc; /// Special pool allocator for VNInfo's (LiveInterval val#). - /// VNInfo::Allocator VNInfoAllocator; /// Live interval pointers for all the virtual registers. IndexedMap<LiveInterval*, VirtReg2IndexFunctor> VirtRegIntervals; - /// RegMaskSlots - Sorted list of instructions with register mask operands. - /// Always use the 'r' slot, RegMasks are normal clobbers, not early - /// clobbers. + /// Sorted list of instructions with register mask operands. Always use the + /// 'r' slot, RegMasks are normal clobbers, not early clobbers. SmallVector<SlotIndex, 8> RegMaskSlots; - /// RegMaskBits - This vector is parallel to RegMaskSlots, it holds a - /// pointer to the corresponding register mask. This pointer can be - /// recomputed as: + /// This vector is parallel to RegMaskSlots, it holds a pointer to the + /// corresponding register mask. This pointer can be recomputed as: /// /// MI = Indexes->getInstructionFromIndex(RegMaskSlot[N]); /// unsigned OpNum = findRegMaskOperand(MI); @@ -97,11 +94,11 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; SmallVector<LiveRange*, 0> RegUnitRanges; public: - static char ID; // Pass identification, replacement for typeid + static char ID; LiveIntervals(); ~LiveIntervals() override; - // Calculate the spill weight to assign to a single instruction. + /// Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, const MachineBlockFrequencyInfo *MBFI, const MachineInstr &Instr); @@ -121,7 +118,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; return VirtRegIntervals.inBounds(Reg) && VirtRegIntervals[Reg]; } - // Interval creation. + /// Interval creation. LiveInterval &createEmptyInterval(unsigned Reg) { assert(!hasInterval(Reg) && "Interval already exists!"); VirtRegIntervals.grow(Reg); @@ -135,7 +132,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; return LI; } - // Interval removal. + /// Interval removal. void removeInterval(unsigned Reg) { delete VirtRegIntervals[Reg]; VirtRegIntervals[Reg] = nullptr; @@ -163,16 +160,16 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; /// LiveInterval::removeEmptySubranges() afterwards. void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); - /// Extend the live range @p LR to reach all points in @p Indices. The - /// points in the @p Indices array must be jointly dominated by the union - /// of the existing defs in @p LR and points in @p Undefs. + /// Extend the live range \p LR to reach all points in \p Indices. The + /// points in the \p Indices array must be jointly dominated by the union + /// of the existing defs in \p LR and points in \p Undefs. /// /// PHI-defs are added as needed to maintain SSA form. /// - /// If a SlotIndex in @p Indices is the end index of a basic block, @p LR + /// If a SlotIndex in \p Indices is the end index of a basic block, \p LR /// will be extended to be live out of the basic block. - /// If a SlotIndex in @p Indices is jointy dominated only by points in - /// @p Undefs, the live range will not be extended to that point. + /// If a SlotIndex in \p Indices is jointy dominated only by points in + /// \p Undefs, the live range will not be extended to that point. /// /// See also LiveRangeCalc::extend(). void extendToIndices(LiveRange &LR, ArrayRef<SlotIndex> Indices, @@ -182,7 +179,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; extendToIndices(LR, Indices, /*Undefs=*/{}); } - /// If @p LR has a live value at @p Kill, prune its live range by removing + /// 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. @@ -192,6 +189,16 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; void pruneValue(LiveRange &LR, SlotIndex Kill, SmallVectorImpl<SlotIndex> *EndPoints); + /// This function should be used. Its intend is to tell you that + /// you are doing something wrong if you call pruveValue directly on a + /// LiveInterval. Indeed, you are supposed to call pruneValue on the main + /// LiveRange and all the LiveRange of the subranges if any. + LLVM_ATTRIBUTE_UNUSED void pruneValue(LiveInterval &, SlotIndex, + SmallVectorImpl<SlotIndex> *) { + llvm_unreachable( + "Use pruneValue on the main LiveRange and on each subrange"); + } + SlotIndexes *getSlotIndexes() const { return Indexes; } @@ -200,8 +207,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; return AA; } - /// isNotInMIMap - returns true if the specified machine instr has been - /// removed or was never entered in the map. + /// Returns true if the specified machine instr has been removed or was + /// never entered in the map. bool isNotInMIMap(const MachineInstr &Instr) const { return !Indexes->hasIndex(Instr); } @@ -270,35 +277,32 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; void getAnalysisUsage(AnalysisUsage &AU) const override; void releaseMemory() override; - /// runOnMachineFunction - pass entry point + /// Pass entry point; Calculates LiveIntervals. bool runOnMachineFunction(MachineFunction&) override; - /// print - Implement the dump method. + /// Implement the dump method. void print(raw_ostream &O, const Module* = nullptr) const override; - /// intervalIsInOneMBB - If LI is confined to a single basic block, return - /// a pointer to that block. If LI is live in to or out of any block, - /// return NULL. + /// If LI is confined to a single basic block, return a pointer to that + /// block. If LI is live in to or out of any block, return NULL. MachineBasicBlock *intervalIsInOneMBB(const LiveInterval &LI) const; /// Returns true if VNI is killed by any PHI-def values in LI. /// This may conservatively return true to avoid expensive computations. bool hasPHIKill(const LiveInterval &LI, const VNInfo *VNI) const; - /// addKillFlags - Add kill flags to any instruction that kills a virtual - /// register. + /// Add kill flags to any instruction that kills a virtual register. void addKillFlags(const VirtRegMap*); - /// handleMove - call this method to notify LiveIntervals that - /// instruction 'mi' has been moved within a basic block. This will update - /// the live intervals for all operands of mi. Moves between basic blocks - /// are not supported. + /// Call this method to notify LiveIntervals that instruction \p MI has been + /// moved within a basic block. This will update the live intervals for all + /// operands of \p MI. Moves between basic blocks are not supported. /// /// \param UpdateFlags Update live intervals for nonallocatable physregs. void handleMove(MachineInstr &MI, bool UpdateFlags = false); - /// moveIntoBundle - Update intervals for operands of MI so that they - /// begin/end on the SlotIndex for BundleStart. + /// Update intervals for operands of \p MI so that they begin/end on the + /// SlotIndex for \p BundleStart. /// /// \param UpdateFlags Update live intervals for nonallocatable physregs. /// @@ -308,10 +312,9 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; void handleMoveIntoBundle(MachineInstr &MI, MachineInstr &BundleStart, bool UpdateFlags = false); - /// repairIntervalsInRange - Update live intervals for instructions in a - /// range of iterators. It is intended for use after target hooks that may - /// insert or remove instructions, and is only efficient for a small number - /// of instructions. + /// Update live intervals for instructions in a range of iterators. It is + /// intended for use after target hooks that may insert or remove + /// instructions, and is only efficient for a small number of instructions. /// /// OrigRegs is a vector of registers that were originally used by the /// instructions in the range between the two iterators. @@ -334,34 +337,33 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; // LiveIntervalAnalysis maintains a sorted list of instructions with // register mask operands. - /// getRegMaskSlots - Returns a sorted array of slot indices of all - /// instructions with register mask operands. + /// Returns a sorted array of slot indices of all instructions with + /// register mask operands. ArrayRef<SlotIndex> getRegMaskSlots() const { return RegMaskSlots; } - /// getRegMaskSlotsInBlock - Returns a sorted array of slot indices of all - /// instructions with register mask operands in the basic block numbered - /// MBBNum. + /// Returns a sorted array of slot indices of all instructions with register + /// mask operands in the basic block numbered \p MBBNum. ArrayRef<SlotIndex> getRegMaskSlotsInBlock(unsigned MBBNum) const { std::pair<unsigned, unsigned> P = RegMaskBlocks[MBBNum]; return getRegMaskSlots().slice(P.first, P.second); } - /// getRegMaskBits() - Returns an array of register mask pointers - /// corresponding to getRegMaskSlots(). + /// Returns an array of register mask pointers corresponding to + /// getRegMaskSlots(). ArrayRef<const uint32_t*> getRegMaskBits() const { return RegMaskBits; } - /// getRegMaskBitsInBlock - Returns an array of mask pointers corresponding - /// to getRegMaskSlotsInBlock(MBBNum). + /// Returns an array of mask pointers corresponding to + /// getRegMaskSlotsInBlock(MBBNum). ArrayRef<const uint32_t*> getRegMaskBitsInBlock(unsigned MBBNum) const { std::pair<unsigned, unsigned> P = RegMaskBlocks[MBBNum]; return getRegMaskBits().slice(P.first, P.second); } - /// checkRegMaskInterference - Test if LI is live across any register mask - /// instructions, and compute a bit mask of physical registers that are not - /// clobbered by any of them. + /// Test if \p LI is live across any register mask instructions, and + /// compute a bit mask of physical registers that are not clobbered by any + /// of them. /// - /// Returns false if LI doesn't cross any register mask instructions. In + /// Returns false if \p LI doesn't cross any register mask instructions. In /// that case, the bit vector is not filled in. bool checkRegMaskInterference(LiveInterval &LI, BitVector &UsableRegs); @@ -377,8 +379,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; // track liveness per register unit to handle aliasing registers more // efficiently. - /// getRegUnit - Return the live range for Unit. - /// It will be computed if it doesn't exist. + /// Return the live range for register unit \p Unit. It will be computed if + /// it doesn't exist. LiveRange &getRegUnit(unsigned Unit) { LiveRange *LR = RegUnitRanges[Unit]; if (!LR) { @@ -390,8 +392,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; return *LR; } - /// getCachedRegUnit - Return the live range for Unit if it has already - /// been computed, or NULL if it hasn't been computed yet. + /// Return the live range for register unit \p Unit if it has already been + /// computed, or nullptr if it hasn't been computed yet. LiveRange *getCachedRegUnit(unsigned Unit) { return RegUnitRanges[Unit]; } @@ -400,7 +402,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; return RegUnitRanges[Unit]; } - /// removeRegUnit - Remove computed live range for Unit. Subsequent uses + /// Remove computed live range for register unit \p Unit. Subsequent uses /// should rely on on-demand recomputation. void removeRegUnit(unsigned Unit) { delete RegUnitRanges[Unit]; @@ -408,12 +410,12 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; } /// 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 + /// \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. + /// 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); /// Split separate components in LiveInterval \p LI into separate intervals. @@ -432,10 +434,10 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); - /// Walk the values in @p LI and check for dead values: + /// 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 + /// - 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. @@ -453,8 +455,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; /// 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 + /// 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, diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index f0f1637dc92d..57e3deb038af 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -1,4 +1,4 @@ -//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===// +//===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -18,7 +18,11 @@ #define LLVM_CODEGEN_LIVEINTERVALUNION_H #include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include <cassert> +#include <limits> namespace llvm { @@ -30,13 +34,6 @@ template <unsigned Element> class SparseBitVector; typedef SparseBitVector<128> LiveVirtRegBitSet; #endif -/// Compare a live virtual register segment to a LiveIntervalUnion segment. -inline bool -overlap(const LiveInterval::Segment &VRSeg, - const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) { - return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end; -} - /// Union of live intervals that are strong candidates for coalescing into a /// single register (either physical or virtual depending on the context). We /// expect the constituent live intervals to be disjoint, although we may @@ -53,29 +50,34 @@ public: // to reach the current segment's containing virtual register. typedef LiveSegments::iterator SegmentIter; + /// Const version of SegmentIter. + typedef LiveSegments::const_iterator ConstSegmentIter; + // LiveIntervalUnions share an external allocator. typedef LiveSegments::Allocator Allocator; - class Query; - private: - unsigned Tag; // unique tag for current contents. + unsigned Tag = 0; // unique tag for current contents. LiveSegments Segments; // union of virtual reg segments public: - explicit LiveIntervalUnion(Allocator &a) : Tag(0), Segments(a) {} + explicit LiveIntervalUnion(Allocator &a) : Segments(a) {} // Iterate over all segments in the union of live virtual registers ordered // by their starting position. SegmentIter begin() { return Segments.begin(); } SegmentIter end() { return Segments.end(); } SegmentIter find(SlotIndex x) { return Segments.find(x); } + ConstSegmentIter begin() const { return Segments.begin(); } + ConstSegmentIter end() const { return Segments.end(); } + ConstSegmentIter find(SlotIndex x) const { return Segments.find(x); } + bool empty() const { return Segments.empty(); } SlotIndex startIndex() const { return Segments.start(); } // Provide public access to the underlying map to allow overlap iteration. typedef LiveSegments Map; - const Map &getMap() { return Segments; } + const Map &getMap() const { return Segments; } /// getTag - Return an opaque tag representing the current state of the union. unsigned getTag() const { return Tag; } @@ -85,15 +87,9 @@ public: // Add a live virtual register to this union and merge its segments. 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, const LiveRange &Range); - void extract(LiveInterval &VirtReg) { - extract(VirtReg, VirtReg); - } // Remove all inserted virtual registers. void clear() { Segments.clear(); ++Tag; } @@ -109,52 +105,42 @@ public: /// Query interferences between a single live virtual register and a live /// interval union. class Query { - LiveIntervalUnion *LiveUnion; - LiveInterval *VirtReg; - LiveInterval::iterator VirtRegI; // current position in VirtReg - SegmentIter LiveUnionI; // current position in LiveUnion + const LiveIntervalUnion *LiveUnion = nullptr; + const LiveRange *LR = nullptr; + LiveRange::const_iterator LRI; ///< current position in LR + ConstSegmentIter LiveUnionI; ///< current position in LiveUnion SmallVector<LiveInterval*,4> InterferingVRegs; - bool CheckedFirstInterference; - bool SeenAllInterferences; - bool SeenUnspillableVReg; - unsigned Tag, UserTag; - - public: - Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {} - - Query(LiveInterval *VReg, LiveIntervalUnion *LIU): - LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false), - SeenAllInterferences(false), SeenUnspillableVReg(false) - {} - - void clear() { - LiveUnion = nullptr; - VirtReg = nullptr; + bool CheckedFirstInterference = false; + bool SeenAllInterferences = false; + unsigned Tag = 0; + unsigned UserTag = 0; + + void reset(unsigned NewUserTag, const LiveRange &NewLR, + const LiveIntervalUnion &NewLiveUnion) { + LiveUnion = &NewLiveUnion; + LR = &NewLR; InterferingVRegs.clear(); CheckedFirstInterference = false; SeenAllInterferences = false; - SeenUnspillableVReg = false; - Tag = 0; - UserTag = 0; + Tag = NewLiveUnion.getTag(); + UserTag = NewUserTag; } - void init(unsigned UTag, LiveInterval *VReg, LiveIntervalUnion *LIU) { - assert(VReg && LIU && "Invalid arguments"); - if (UserTag == UTag && VirtReg == VReg && - LiveUnion == LIU && !LIU->changedSince(Tag)) { + public: + Query() = default; + Query(const LiveRange &LR, const LiveIntervalUnion &LIU): + LiveUnion(&LIU), LR(&LR) {} + Query(const Query &) = delete; + Query &operator=(const Query &) = delete; + + void init(unsigned NewUserTag, const LiveRange &NewLR, + const LiveIntervalUnion &NewLiveUnion) { + if (UserTag == NewUserTag && LR == &NewLR && LiveUnion == &NewLiveUnion && + !NewLiveUnion.changedSince(Tag)) { // Retain cached results, e.g. firstInterference. return; } - clear(); - LiveUnion = LIU; - VirtReg = VReg; - Tag = LIU->getTag(); - UserTag = UTag; - } - - LiveInterval &virtReg() const { - assert(VirtReg && "uninitialized"); - return *VirtReg; + reset(NewUserTag, NewLR, NewLiveUnion); } // Does this live virtual register interfere with the union? @@ -162,7 +148,8 @@ public: // Count the virtual registers in this union that interfere with this // query's live virtual register, up to maxInterferingRegs. - unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX); + unsigned collectInterferingVRegs( + unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max()); // Was this virtual register visited during collectInterferingVRegs? bool isSeenInterference(LiveInterval *VReg) const; @@ -170,25 +157,19 @@ public: // Did collectInterferingVRegs collect all interferences? bool seenAllInterferences() const { return SeenAllInterferences; } - // Did collectInterferingVRegs encounter an unspillable vreg? - bool seenUnspillableVReg() const { return SeenUnspillableVReg; } - // Vector generated by collectInterferingVRegs. const SmallVectorImpl<LiveInterval*> &interferingVRegs() const { return InterferingVRegs; } - - private: - Query(const Query&) = delete; - void operator=(const Query&) = delete; }; // Array of LiveIntervalUnions. class Array { - unsigned Size; - LiveIntervalUnion *LIUs; + unsigned Size = 0; + LiveIntervalUnion *LIUs = nullptr; + public: - Array() : Size(0), LIUs(nullptr) {} + Array() = default; ~Array() { clear(); } // Initialize the array to have Size entries. @@ -213,4 +194,4 @@ public: } // end namespace llvm -#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION_H) +#endif // LLVM_CODEGEN_LIVEINTERVALUNION_H diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index e169058ca563..fa6827f6b1f9 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -1,4 +1,4 @@ -//===-- LiveRegMatrix.h - Track register interference ---------*- C++ -*---===// +//===- LiveRegMatrix.h - Track register interference ----------*- C++ -*---===// // // The LLVM Compiler Infrastructure // @@ -27,11 +27,14 @@ #include "llvm/ADT/BitVector.h" #include "llvm/CodeGen/LiveIntervalUnion.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include <memory> namespace llvm { +class AnalysisUsage; class LiveInterval; -class LiveIntervalAnalysis; +class LiveIntervals; +class MachineFunction; class TargetRegisterInfo; class VirtRegMap; @@ -41,7 +44,7 @@ class LiveRegMatrix : public MachineFunctionPass { VirtRegMap *VRM; // UserTag changes whenever virtual registers have been modified. - unsigned UserTag; + unsigned UserTag = 0; // The matrix is represented as a LiveIntervalUnion per register unit. LiveIntervalUnion::Allocator LIUAlloc; @@ -51,16 +54,18 @@ class LiveRegMatrix : public MachineFunctionPass { std::unique_ptr<LiveIntervalUnion::Query[]> Queries; // Cached register mask interference info. - unsigned RegMaskTag; - unsigned RegMaskVirtReg; + unsigned RegMaskTag = 0; + unsigned RegMaskVirtReg = 0; BitVector RegMaskUsable; // MachineFunctionPass boilerplate. - void getAnalysisUsage(AnalysisUsage&) const override; - bool runOnMachineFunction(MachineFunction&) override; + void getAnalysisUsage(AnalysisUsage &) const override; + bool runOnMachineFunction(MachineFunction &) override; void releaseMemory() override; + public: static char ID; + LiveRegMatrix(); //===--------------------------------------------------------------------===// @@ -136,7 +141,7 @@ public: /// Use MCRegUnitIterator to enumerate all regunits in the desired PhysReg. /// This returns a reference to an internal Query data structure that is only /// valid until the next query() call. - LiveIntervalUnion::Query &query(LiveInterval &VirtReg, unsigned RegUnit); + LiveIntervalUnion::Query &query(const LiveRange &LR, unsigned RegUnit); /// Directly access the live interval unions per regunit. /// This returns an array indexed by the regunit number. diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h new file mode 100644 index 000000000000..5de76c8b87bf --- /dev/null +++ b/include/llvm/CodeGen/LiveRegUnits.h @@ -0,0 +1,128 @@ +//===- llvm/CodeGen/LiveRegUnits.h - Register Unit Set ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// A set of register units. It is intended for register liveness tracking. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEREGUNITS_H +#define LLVM_CODEGEN_LIVEREGUNITS_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/MC/LaneBitmask.h" +#include "llvm/MC/MCRegisterInfo.h" +#include <cstdint> + +namespace llvm { + +class MachineInstr; +class MachineBasicBlock; + +/// A set of register units used to track register liveness. +class LiveRegUnits { + const TargetRegisterInfo *TRI = nullptr; + BitVector Units; + +public: + /// Constructs a new empty LiveRegUnits set. + LiveRegUnits() = default; + + /// Constructs and initialize an empty LiveRegUnits set. + LiveRegUnits(const TargetRegisterInfo &TRI) { + init(TRI); + } + + /// Initialize and clear the set. + void init(const TargetRegisterInfo &TRI) { + this->TRI = &TRI; + Units.reset(); + Units.resize(TRI.getNumRegUnits()); + } + + /// Clears the set. + void clear() { Units.reset(); } + + /// Returns true if the set is empty. + bool empty() const { return Units.empty(); } + + /// Adds register units covered by physical register \p Reg. + void addReg(unsigned Reg) { + for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) + Units.set(*Unit); + } + + /// \brief Adds register units covered by physical register \p Reg that are + /// part of the lanemask \p Mask. + void addRegMasked(unsigned Reg, LaneBitmask Mask) { + for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { + LaneBitmask UnitMask = (*Unit).second; + if (UnitMask.none() || (UnitMask & Mask).any()) + Units.set((*Unit).first); + } + } + + /// Removes all register units covered by physical register \p Reg. + void removeReg(unsigned Reg) { + for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) + Units.reset(*Unit); + } + + /// Removes register units not preserved by the regmask \p RegMask. + /// The regmask has the same format as the one in the RegMask machine operand. + void removeRegsNotPreserved(const uint32_t *RegMask); + + /// Adds register units not preserved by the regmask \p RegMask. + /// The regmask has the same format as the one in the RegMask machine operand. + void addRegsInMask(const uint32_t *RegMask); + + /// Returns true if no part of physical register \p Reg is live. + bool available(unsigned Reg) const { + for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { + if (Units.test(*Unit)) + return false; + } + return true; + } + + /// Updates liveness when stepping backwards over the instruction \p MI. + void stepBackward(const MachineInstr &MI); + + /// Mark all register units live during instruction \p MI. + /// This can be used to accumulate live/unoccupied registers over a range of + /// instructions. + void accumulateBackward(const MachineInstr &MI); + + /// Adds registers living out of block \p MBB. + /// Live out registers are the union of the live-in registers of the successor + /// blocks and pristine registers. Live out registers of the end block are the + /// callee saved registers. + void addLiveOuts(const MachineBasicBlock &MBB); + + /// Adds registers living into block \p MBB. + void addLiveIns(const MachineBasicBlock &MBB); + + /// Adds all register units marked in the bitvector \p RegUnits. + void addUnits(const BitVector &RegUnits) { + Units |= RegUnits; + } + /// Removes all register units marked in the bitvector \p RegUnits. + void removeUnits(const BitVector &RegUnits) { + Units.reset(RegUnits); + } + /// Return the internal bitvector representation of the set. + const BitVector &getBitVector() const { + return Units; + } +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_LIVEREGUNITS_H diff --git a/include/llvm/CodeGen/LowLevelType.h b/include/llvm/CodeGen/LowLevelType.h index b8885c3a95fd..a3c5c9329f53 100644 --- a/include/llvm/CodeGen/LowLevelType.h +++ b/include/llvm/CodeGen/LowLevelType.h @@ -1,4 +1,4 @@ -//== llvm/CodeGen/GlobalISel/LowLevelType.h -------------------- -*- C++ -*-==// +//== llvm/CodeGen/LowLevelType.h ------------------------------- -*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -10,197 +10,23 @@ /// Implement a low-level type suitable for MachineInstr level instruction /// selection. /// -/// For a type attached to a MachineInstr, we only care about 2 details: total -/// size and the number of vector lanes (if any). Accordingly, there are 4 -/// possible valid type-kinds: -/// -/// * `sN` for scalars and aggregates -/// * `<N x sM>` for vectors, which must have at least 2 elements. -/// * `pN` for pointers -/// -/// Other information required for correct selection is expected to be carried -/// by the opcode, or non-type flags. For example the distinction between G_ADD -/// and G_FADD for int/float or fast-math flags. +/// This provides the CodeGen aspects of LowLevelType, such as Type conversion. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H -#define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H +#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H +#define LLVM_CODEGEN_LOWLEVELTYPE_H -#include <cassert> -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/LowLevelTypeImpl.h" namespace llvm { class DataLayout; -class LLVMContext; class Type; -class raw_ostream; - -class LLT { -public: - enum TypeKind : uint16_t { - Invalid, - Scalar, - Pointer, - Vector, - }; - - /// Get a low-level scalar or aggregate "bag of bits". - static LLT scalar(unsigned SizeInBits) { - assert(SizeInBits > 0 && "invalid scalar size"); - return LLT{Scalar, 1, SizeInBits}; - } - - /// Get a low-level pointer in the given address space (defaulting to 0). - static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) { - return LLT{Pointer, AddressSpace, SizeInBits}; - } - - /// Get a low-level vector of some number of elements and element width. - /// \p NumElements must be at least 2. - static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) { - assert(NumElements > 1 && "invalid number of vector elements"); - return LLT{Vector, NumElements, ScalarSizeInBits}; - } - - /// Get a low-level vector of some number of elements and element type. - static LLT vector(uint16_t NumElements, LLT ScalarTy) { - assert(NumElements > 1 && "invalid number of vector elements"); - assert(ScalarTy.isScalar() && "invalid vector element type"); - return LLT{Vector, NumElements, ScalarTy.getSizeInBits()}; - } - - explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits) - : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) { - assert((Kind != Vector || ElementsOrAddrSpace > 1) && - "invalid number of vector elements"); - } - - explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {} - - /// Construct a low-level type based on an LLVM type. - explicit LLT(Type &Ty, const DataLayout &DL); - - explicit LLT(MVT VT); - - bool isValid() const { return Kind != Invalid; } - - bool isScalar() const { return Kind == Scalar; } - - bool isPointer() const { return Kind == Pointer; } - - bool isVector() const { return Kind == Vector; } - - /// Returns the number of elements in a vector LLT. Must only be called on - /// vector types. - uint16_t getNumElements() const { - assert(isVector() && "cannot get number of elements on scalar/aggregate"); - return ElementsOrAddrSpace; - } - - /// Returns the total size of the type. Must only be called on sized types. - unsigned getSizeInBits() const { - if (isPointer() || isScalar()) - return SizeInBits; - return SizeInBits * ElementsOrAddrSpace; - } - - unsigned getScalarSizeInBits() const { - return SizeInBits; - } - - unsigned getAddressSpace() const { - assert(isPointer() && "cannot get address space of non-pointer type"); - return ElementsOrAddrSpace; - } - - /// Returns the vector's element type. Only valid for vector types. - LLT getElementType() const { - assert(isVector() && "cannot get element type of scalar/aggregate"); - return scalar(SizeInBits); - } - - /// Get a low-level type with half the size of the original, by halving the - /// size of the scalar type involved. For example `s32` will become `s16`, - /// `<2 x s32>` will become `<2 x s16>`. - LLT halfScalarSize() const { - assert(!isPointer() && getScalarSizeInBits() > 1 && - getScalarSizeInBits() % 2 == 0 && "cannot half size of this type"); - return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2}; - } - - /// Get a low-level type with twice the size of the original, by doubling the - /// size of the scalar type involved. For example `s32` will become `s64`, - /// `<2 x s32>` will become `<2 x s64>`. - LLT doubleScalarSize() const { - assert(!isPointer() && "cannot change size of this type"); - return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2}; - } - - /// Get a low-level type with half the size of the original, by halving the - /// number of vector elements of the scalar type involved. The source must be - /// a vector type with an even number of elements. For example `<4 x s32>` - /// will become `<2 x s32>`, `<2 x s32>` will become `s32`. - LLT halfElements() const { - assert(isVector() && ElementsOrAddrSpace % 2 == 0 && - "cannot half odd vector"); - if (ElementsOrAddrSpace == 2) - return scalar(SizeInBits); - - return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2), - SizeInBits}; - } - - /// Get a low-level type with twice the size of the original, by doubling the - /// number of vector elements of the scalar type involved. The source must be - /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling - /// the number of elements in sN produces <2 x sN>. - LLT doubleElements() const { - assert(!isPointer() && "cannot double elements in pointer"); - return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2), - SizeInBits}; - } - - void print(raw_ostream &OS) const; - - bool operator==(const LLT &RHS) const { - return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits && - ElementsOrAddrSpace == RHS.ElementsOrAddrSpace; - } - - bool operator!=(const LLT &RHS) const { return !(*this == RHS); } - - friend struct DenseMapInfo<LLT>; -private: - unsigned SizeInBits; - uint16_t ElementsOrAddrSpace; - TypeKind Kind; -}; - -inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) { - Ty.print(OS); - return OS; -} -template<> struct DenseMapInfo<LLT> { - static inline LLT getEmptyKey() { - return LLT{LLT::Invalid, 0, -1u}; - } - static inline LLT getTombstoneKey() { - return LLT{LLT::Invalid, 0, -2u}; - } - static inline unsigned getHashValue(const LLT &Ty) { - uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) | - ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind; - return DenseMapInfo<uint64_t>::getHashValue(Val); - } - static bool isEqual(const LLT &LHS, const LLT &RHS) { - return LHS == RHS; - } -}; +/// Construct a low-level type based on an LLVM type. +LLT getLLTForType(Type &Ty, const DataLayout &DL); } -#endif +#endif // LLVM_CODEGEN_LOWLEVELTYPE_H diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h index 778f72c06e65..38cf8aa165a4 100644 --- a/include/llvm/CodeGen/MIRYamlMapping.h +++ b/include/llvm/CodeGen/MIRYamlMapping.h @@ -55,7 +55,7 @@ template <> struct ScalarTraits<StringValue> { struct FlowStringValue : StringValue { FlowStringValue() {} - FlowStringValue(std::string Value) : StringValue(Value) {} + FlowStringValue(std::string Value) : StringValue(std::move(Value)) {} }; template <> struct ScalarTraits<FlowStringValue> { @@ -381,6 +381,7 @@ struct MachineFunction { StringRef Name; unsigned Alignment = 0; bool ExposesReturnsTwice = false; + bool NoVRegs; // GISel MachineFunctionProperties. bool Legalized = false; bool RegBankSelected = false; @@ -405,6 +406,7 @@ template <> struct MappingTraits<MachineFunction> { YamlIO.mapRequired("name", MF.Name); YamlIO.mapOptional("alignment", MF.Alignment); YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice); + YamlIO.mapOptional("noVRegs", MF.NoVRegs); YamlIO.mapOptional("legalized", MF.Legalized); YamlIO.mapOptional("regBankSelected", MF.RegBankSelected); YamlIO.mapOptional("selected", MF.Selected); diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index f3f5e324d76a..18d40564856d 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -128,7 +128,7 @@ public: /// to an LLVM basic block. const BasicBlock *getBasicBlock() const { return BB; } - /// Return the name of the corresponding LLVM basic block, or "(null)". + /// Return the name of the corresponding LLVM basic block, or an empty string. StringRef getName() const; /// Return a formatted string to identify this block and its parent function. @@ -455,10 +455,19 @@ public: /// other block. bool isLayoutSuccessor(const MachineBasicBlock *MBB) const; - /// Return true if the block can implicitly transfer control to the block - /// after it by falling off the end of it. This should return false if it can - /// reach the block after it, but it uses an explicit branch to do so (e.g., a - /// table jump). True is a conservative answer. + + /// Return the fallthrough block if the block can implicitly + /// transfer control to the block after it by falling off the end of + /// it. This should return null if it can reach the block after + /// it, but it uses an explicit branch to do so (e.g., a table + /// jump). Non-null return is a conservative answer. + MachineBasicBlock *getFallThrough(); + + /// Return true if the block can implicitly transfer control to the + /// block after it by falling off the end of it. This should return + /// false if it can reach the block after it, but it uses an + /// explicit branch to do so (e.g., a table jump). True is a + /// conservative answer. bool canFallThrough(); /// Returns a pointer to the first instruction in this block that is not a @@ -664,6 +673,10 @@ public: return findDebugLoc(MBBI.getInstrIterator()); } + /// Find and return the merged DebugLoc of the branch instructions of the + /// block. Return UnknownLoc if there is none. + DebugLoc findBranchDebugLoc(); + /// Possible outcome of a register liveness query to computeRegisterLiveness() enum LivenessQueryResult { LQR_Live, ///< Register is known to be (at least partially) live. diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index bfa5bf6c2845..cd1c204981ed 100644 --- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -23,6 +23,7 @@ namespace llvm { class MachineBasicBlock; class MachineBranchProbabilityInfo; +class MachineLoopInfo; template <class BlockT> class BlockFrequencyInfoImpl; /// MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation @@ -42,6 +43,11 @@ public: bool runOnMachineFunction(MachineFunction &F) override; + /// calculate - compute block frequency info for the given function. + void calculate(const MachineFunction &F, + const MachineBranchProbabilityInfo &MBPI, + const MachineLoopInfo &MLI); + void releaseMemory() override; /// getblockFreq - Return block frequency. Return 0 if we don't have the @@ -56,7 +62,7 @@ public: const MachineFunction *getFunction() const; const MachineBranchProbabilityInfo *getMBPI() const; - void view() const; + void view(const Twine &Name, bool isSimple = true) const; // Print the block frequency Freq to OS using the current functions entry // frequency to convert freq into a relative decimal form. diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 21ecef587aa5..30b6cfdd1c36 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Support/GenericDomTree.h" #include "llvm/Support/GenericDomTreeConstruction.h" +#include <memory> namespace llvm { @@ -60,7 +61,7 @@ class MachineDominatorTree : public MachineFunctionPass { mutable SmallSet<MachineBasicBlock *, 32> NewBBs; /// The DominatorTreeBase that is used to compute a normal dominator tree - DominatorTreeBase<MachineBasicBlock>* DT; + std::unique_ptr<DominatorTreeBase<MachineBasicBlock>> DT; /// \brief Apply all the recorded critical edges to the DT. /// This updates the underlying DT information in a way that uses @@ -74,9 +75,9 @@ public: MachineDominatorTree(); - ~MachineDominatorTree() override; - DominatorTreeBase<MachineBasicBlock> &getBase() { + if (!DT) + DT.reset(new DominatorTreeBase<MachineBasicBlock>(false)); applySplitCriticalEdges(); return *DT; } @@ -244,21 +245,6 @@ public: CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB}); } - /// \brief Returns *false* if the other dominator tree matches this dominator - /// tree. - inline bool compare(const MachineDominatorTree &Other) const { - const MachineDomTreeNode *R = getRootNode(); - const MachineDomTreeNode *OtherR = Other.getRootNode(); - - if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) - return true; - - if (DT->compare(*Other.DT)) - return true; - - return false; - } - /// \brief Verify the correctness of the domtree by re-computing it. /// /// This should only be used for debugging as it aborts the program if the diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 4600c2c0f10c..5c9728b0a51e 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -559,8 +559,7 @@ public: return Objects[ObjectIdx+NumFixedObjects].isAliased; } - /// isImmutableObjectIndex - Returns true if the specified index corresponds - /// to an immutable object. + /// Returns true if the specified index corresponds to an immutable object. bool isImmutableObjectIndex(int ObjectIdx) const { // Tail calling functions can clobber their function arguments. if (HasTailCall) @@ -570,6 +569,13 @@ public: return Objects[ObjectIdx+NumFixedObjects].isImmutable; } + /// Marks the immutability of an object. + void setIsImmutableObjectIndex(int ObjectIdx, bool Immutable) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + Objects[ObjectIdx+NumFixedObjects].isImmutable = Immutable; + } + /// Returns true if the specified index corresponds to a spill slot. bool isSpillSlotObjectIndex(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 0c21b3254631..5859a4e61fdd 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -475,9 +475,8 @@ public: /// getBlockNumbered - MachineBasicBlocks are automatically numbered when they /// are inserted into the machine function. The block number for a machine - /// basic block can be found by using the MBB::getBlockNumber method, this - /// method provides the inverse mapping. - /// + /// basic block can be found by using the MBB::getNumber method, this method + /// provides the inverse mapping. MachineBasicBlock *getBlockNumbered(unsigned N) const { assert(N < MBBNumbering.size() && "Illegal block number"); assert(MBBNumbering[N] && "Block was removed from the machine function!"); diff --git a/include/llvm/CodeGen/MachineFunctionInitializer.h b/include/llvm/CodeGen/MachineFunctionInitializer.h index ff4c29cc014d..c644c9783e2f 100644 --- a/include/llvm/CodeGen/MachineFunctionInitializer.h +++ b/include/llvm/CodeGen/MachineFunctionInitializer.h @@ -1,4 +1,4 @@ -//===- MachineFunctionInitalizer.h - machine function initializer ---------===// +//===- MachineFunctionInitializer.h - machine function initializer ---------===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index bac93e5d3a4c..e7e728c1be28 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -1108,6 +1108,18 @@ public: /// the instruction's location and its intended destination. bool isSafeToMove(AliasAnalysis *AA, bool &SawStore) const; + /// Returns true if this instruction's memory access aliases the memory + /// access of Other. + // + /// Assumes any physical registers used to compute addresses + /// have the same value for both instructions. Returns false if neither + /// instruction writes to memory. + /// + /// @param AA Optional alias analysis, used to compare memory operands. + /// @param Other MachineInstr to check aliasing against. + /// @param UseTBAA Whether to pass TBAA information to alias analysis. + bool mayAlias(AliasAnalysis *AA, MachineInstr &Other, bool UseTBAA); + /// Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory /// reference is not available. Return false if it is known to have no @@ -1146,14 +1158,21 @@ public: /// instruction to this instruction. void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI); - // - // Debugging support - // - void print(raw_ostream &OS, bool SkipOpers = false, + /// Debugging support + /// @{ + /// Print this MI to \p OS. + /// Only print the defs and the opcode if \p SkipOpers is true. + /// Otherwise, also print operands if \p SkipDebugLoc is true. + /// Otherwise, also print the debug loc, with a terminating newline. + /// \p TII is used to print the opcode name. If it's not present, but the + /// MI is in a function, the opcode will be printed using the function's TII. + void print(raw_ostream &OS, bool SkipOpers = false, bool SkipDebugLoc = false, const TargetInstrInfo *TII = nullptr) const; void print(raw_ostream &OS, ModuleSlotTracker &MST, bool SkipOpers = false, + bool SkipDebugLoc = false, const TargetInstrInfo *TII = nullptr) const; - void dump(const TargetInstrInfo *TII = nullptr) const; + void dump() const; + /// @} //===--------------------------------------------------------------------===// // Accessors used to build up machine instructions. diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 3c8a3626f364..ef4226d30fe3 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -1,4 +1,4 @@ -//===-- CodeGen/MachineInstBuilder.h - Simplify creation of MIs -*- C++ -*-===// +//===- CodeGen/MachineInstrBuilder.h - Simplify creation of MIs --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,9 +19,18 @@ #ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H #define LLVM_CODEGEN_MACHINEINSTRBUILDER_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstdint> +#include <utility> namespace llvm { @@ -29,6 +38,7 @@ class MCInstrDesc; class MDNode; namespace RegState { + enum { Define = 0x2, Implicit = 0x4, @@ -42,13 +52,15 @@ namespace RegState { ImplicitDefine = Implicit | Define, ImplicitKill = Implicit | Kill }; -} + +} // end namespace RegState class MachineInstrBuilder { - MachineFunction *MF; - MachineInstr *MI; + MachineFunction *MF = nullptr; + MachineInstr *MI = nullptr; + public: - MachineInstrBuilder() : MF(nullptr), MI(nullptr) {} + MachineInstrBuilder() = default; /// Create a MachineInstrBuilder for manipulating an existing instruction. /// F must be the machine function that was used to allocate I. @@ -187,11 +199,18 @@ public: return *this; } - const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { + const MachineInstrBuilder &add(const MachineOperand &MO) const { MI->addOperand(*MF, MO); return *this; } + const MachineInstrBuilder &add(ArrayRef<MachineOperand> MOs) const { + for (const MachineOperand &MO : MOs) { + MI->addOperand(*MF, MO); + } + return *this; + } + const MachineInstrBuilder &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) @@ -511,6 +530,6 @@ public: } }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_MACHINEINSTRBUILDER_H diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index dc72ae1810ee..5c814f22f99b 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -60,6 +60,13 @@ public: /// multiple exiting blocks are present. MachineBasicBlock *findLoopControlBlock(); + /// Return the debug location of the start of this loop. + /// This looks for a BB terminating instruction with a known debug + /// location by looking at the preheader and header blocks. If it + /// cannot find a terminating instruction with location information, + /// it returns an unknown location. + DebugLoc getStartLoc() const; + void dump() const; private: diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h index f9fa6999073f..f28a79c5b5cc 100644 --- a/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -15,7 +15,9 @@ #ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H #define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Support/Wasm.h" namespace llvm { class MCSymbol; @@ -75,6 +77,33 @@ public: SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } }; +/// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation +/// for Wasm targets. +class MachineModuleInfoWasm : public MachineModuleInfoImpl { + /// WebAssembly global variables defined by CodeGen. + std::vector<wasm::Global> Globals; + + /// The WebAssembly global variable which is the stack pointer. + unsigned StackPointerGlobal; + + virtual void anchor(); // Out of line virtual method. +public: + MachineModuleInfoWasm(const MachineModuleInfo &) + : StackPointerGlobal(-1U) {} + + void addGlobal(const wasm::Global &G) { Globals.push_back(G); } + const std::vector<wasm::Global> &getGlobals() const { return Globals; } + + bool hasStackPointerGlobal() const { + return StackPointerGlobal != -1U; + } + unsigned getStackPointerGlobal() const { + assert(hasStackPointerGlobal() && "Stack ptr global hasn't been set"); + return StackPointerGlobal; + } + void setStackPointerGlobal(unsigned Global) { StackPointerGlobal = Global; } +}; + } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 5df99a6c807e..81b43126adeb 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -65,6 +65,7 @@ public: MO_CFIIndex, ///< MCCFIInstruction index. MO_IntrinsicID, ///< Intrinsic ID for ISel MO_Predicate, ///< Generic predicate for ISel + MO_Placeholder, ///< Placeholder for GlobalISel ComplexPattern result. }; private: @@ -229,7 +230,7 @@ public: void print(raw_ostream &os, ModuleSlotTracker &MST, const TargetRegisterInfo *TRI = nullptr, const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const; - LLVM_DUMP_METHOD void dump() const; + void dump() const; //===--------------------------------------------------------------------===// // Accessors that tell you what kind of MachineOperand you're looking at. @@ -355,7 +356,7 @@ public: void setReg(unsigned Reg); void setSubReg(unsigned subReg) { - assert(isReg() && "Wrong MachineOperand accessor"); + assert(isReg() && "Wrong MachineOperand mutator"); SubReg_TargetFlags = subReg; assert(SubReg_TargetFlags == subReg && "SubReg out of range"); } @@ -378,38 +379,38 @@ public: void setIsDef(bool Val = true); void setImplicit(bool Val = true) { - assert(isReg() && "Wrong MachineOperand accessor"); + assert(isReg() && "Wrong MachineOperand mutator"); IsImp = Val; } void setIsKill(bool Val = true) { - assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && !IsDef && "Wrong MachineOperand mutator"); assert((!Val || !isDebug()) && "Marking a debug operation as kill"); IsKill = Val; } void setIsDead(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && IsDef && "Wrong MachineOperand mutator"); IsDead = Val; } void setIsUndef(bool Val = true) { - assert(isReg() && "Wrong MachineOperand accessor"); + assert(isReg() && "Wrong MachineOperand mutator"); IsUndef = Val; } void setIsInternalRead(bool Val = true) { - assert(isReg() && "Wrong MachineOperand accessor"); + assert(isReg() && "Wrong MachineOperand mutator"); IsInternalRead = Val; } void setIsEarlyClobber(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && IsDef && "Wrong MachineOperand mutator"); IsEarlyClobber = Val; } void setIsDebug(bool Val = true) { - assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && !IsDef && "Wrong MachineOperand mutator"); IsDebug = Val; } @@ -538,19 +539,19 @@ public: void setOffset(int64_t Offset) { assert((isGlobal() || isSymbol() || isMCSymbol() || isCPI() || isTargetIndex() || isBlockAddress()) && - "Wrong MachineOperand accessor"); + "Wrong MachineOperand mutator"); SmallContents.OffsetLo = unsigned(Offset); Contents.OffsetedInfo.OffsetHi = int(Offset >> 32); } void setIndex(int Idx) { assert((isFI() || isCPI() || isTargetIndex() || isJTI()) && - "Wrong MachineOperand accessor"); + "Wrong MachineOperand mutator"); Contents.OffsetedInfo.Val.Index = Idx; } void setMBB(MachineBasicBlock *MBB) { - assert(isMBB() && "Wrong MachineOperand accessor"); + assert(isMBB() && "Wrong MachineOperand mutator"); Contents.MBB = MBB; } @@ -767,6 +768,11 @@ public: return Op; } + static MachineOperand CreatePlaceholder() { + MachineOperand Op(MachineOperand::MO_Placeholder); + return Op; + } + friend class MachineInstr; friend class MachineRegisterInfo; private: diff --git a/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h new file mode 100644 index 000000000000..da8fdcdf5a33 --- /dev/null +++ b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h @@ -0,0 +1,203 @@ +///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===// +/// +/// The LLVM Compiler Infrastructure +/// +/// This file is distributed under the University of Illinois Open Source +/// License. See LICENSE.TXT for details. +/// +///===---------------------------------------------------------------------===// +/// \file +/// Optimization diagnostic interfaces for machine passes. It's packaged as an +/// analysis pass so that by using this service passes become dependent on MBFI +/// as well. MBFI is used to compute the "hotness" of the diagnostic message. +/// +///===---------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H +#define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H + +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { +class MachineBasicBlock; +class MachineBlockFrequencyInfo; +class MachineInstr; + +/// \brief Common features for diagnostics dealing with optimization remarks +/// that are used by machine passes. +class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase { +public: + DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName, + StringRef RemarkName, + const DiagnosticLocation &Loc, + const MachineBasicBlock *MBB) + : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName, + *MBB->getParent()->getFunction(), Loc), + MBB(MBB) {} + + /// MI-specific kinds of diagnostic Arguments. + struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument { + /// Print an entire MachineInstr. + MachineArgument(StringRef Key, const MachineInstr &MI); + }; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() >= DK_FirstMachineRemark && + DI->getKind() <= DK_LastMachineRemark; + } + + const MachineBasicBlock *getBlock() const { return MBB; } + +private: + const MachineBasicBlock *MBB; +}; + +/// Diagnostic information for applied optimization remarks. +class MachineOptimizationRemark : public DiagnosticInfoMIROptimization { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If this name + /// matches the regular expression given in -Rpass=, then the diagnostic will + /// be emitted. \p RemarkName is a textual identifier for the remark. \p + /// Loc is the debug location and \p MBB is the block that the optimization + /// operates in. + MachineOptimizationRemark(const char *PassName, StringRef RemarkName, + const DiagnosticLocation &Loc, + const MachineBasicBlock *MBB) + : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName, + RemarkName, Loc, MBB) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_MachineOptimizationRemark; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + bool isEnabled() const override { + return OptimizationRemark::isEnabled(getPassName()); + } +}; + +/// Diagnostic information for missed-optimization remarks. +class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If this name + /// matches the regular expression given in -Rpass-missed=, then the + /// diagnostic will be emitted. \p RemarkName is a textual identifier for the + /// remark. \p Loc is the debug location and \p MBB is the block that the + /// optimization operates in. + MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName, + const DiagnosticLocation &Loc, + const MachineBasicBlock *MBB) + : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed, + PassName, RemarkName, Loc, MBB) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_MachineOptimizationRemarkMissed; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + bool isEnabled() const override { + return OptimizationRemarkMissed::isEnabled(getPassName()); + } +}; + +/// Diagnostic information for optimization analysis remarks. +class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If this name + /// matches the regular expression given in -Rpass-analysis=, then the + /// diagnostic will be emitted. \p RemarkName is a textual identifier for the + /// remark. \p Loc is the debug location and \p MBB is the block that the + /// optimization operates in. + MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, + const DiagnosticLocation &Loc, + const MachineBasicBlock *MBB) + : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis, + PassName, RemarkName, Loc, MBB) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_MachineOptimizationRemarkAnalysis; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + bool isEnabled() const override { + return OptimizationRemarkAnalysis::isEnabled(getPassName()); + } +}; + +/// Extend llvm::ore:: with MI-specific helper names. +namespace ore { +using MNV = DiagnosticInfoMIROptimization::MachineArgument; +} + +/// The optimization diagnostic interface. +/// +/// It allows reporting when optimizations are performed and when they are not +/// along with the reasons for it. Hotness information of the corresponding +/// code region can be included in the remark if DiagnosticHotnessRequested is +/// enabled in the LLVM context. +class MachineOptimizationRemarkEmitter { +public: + MachineOptimizationRemarkEmitter(MachineFunction &MF, + MachineBlockFrequencyInfo *MBFI) + : MF(MF), MBFI(MBFI) {} + + /// Emit an optimization remark. + void emit(DiagnosticInfoOptimizationBase &OptDiag); + + /// \brief Whether we allow for extra compile-time budget to perform more + /// analysis to be more informative. + /// + /// This is useful to enable additional missed optimizations to be reported + /// that are normally too noisy. In this mode, we can use the extra analysis + /// (1) to filter trivial false positives or (2) to provide more context so + /// that non-trivial false positives can be quickly detected by the user. + bool allowExtraAnalysis() const { + // For now, only allow this with -fsave-optimization-record since the -Rpass + // options are handled in the front-end. + return MF.getFunction()->getContext().getDiagnosticsOutputFile(); + } + +private: + MachineFunction &MF; + + /// MBFI is only set if hotness is requested. + MachineBlockFrequencyInfo *MBFI; + + /// Compute hotness from IR value (currently assumed to be a block) if PGO is + /// available. + Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB); + + /// Similar but use value from \p OptDiag and update hotness there. + void computeHotness(DiagnosticInfoMIROptimization &Remark); + + /// \brief Only allow verbose messages if we know we're filtering by hotness + /// (BFI is only set in this case). + bool shouldEmitVerbose() { return MBFI != nullptr; } +}; + +/// The analysis pass +/// +/// Note that this pass shouldn't generally be marked as preserved by other +/// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI +/// could be freed. +class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass { + std::unique_ptr<MachineOptimizationRemarkEmitter> ORE; + +public: + MachineOptimizationRemarkEmitterPass(); + + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + MachineOptimizationRemarkEmitter &getORE() { + assert(ORE && "pass not run yet"); + return *ORE; + } + + static char ID; +}; +} + +#endif diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index c599caf7535d..6e5c6473ff4a 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/MachineRegisterInfo.h ----------------------*- C++ -*-===// +//===- llvm/CodeGen/MachineRegisterInfo.h -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,19 +15,29 @@ #define LLVM_CODEGEN_MACHINEREGISTERINFO_H #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/iterator_range.h" -// PointerUnion needs to have access to the full RegisterBank type. +#include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/LowLevelType.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/MC/LaneBitmask.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" #include <vector> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <memory> +#include <utility> namespace llvm { + class PSetIterator; /// Convenient type to represent either a register class or a register bank. @@ -41,15 +51,16 @@ class MachineRegisterInfo { public: class Delegate { virtual void anchor(); + public: - virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0; + virtual ~Delegate() = default; - virtual ~Delegate() {} + virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0; }; private: MachineFunction *MF; - Delegate *TheDelegate; + Delegate *TheDelegate = nullptr; /// True if subregister liveness is tracked. const bool TracksSubRegLiveness; @@ -62,6 +73,15 @@ private: VirtReg2IndexFunctor> VRegInfo; + /// The flag is true upon \p UpdatedCSRs initialization + /// and false otherwise. + bool IsUpdatedCSRsInitialized; + + /// Contains the updated callee saved register list. + /// As opposed to the static list defined in register info, + /// all registers that were disabled are removed from the list. + SmallVector<MCPhysReg, 16> UpdatedCSRs; + /// RegAllocHints - This vector records register allocation hints for virtual /// registers. For each virtual register, it keeps a register and hint type /// pair making up the allocation hint. Hint type is target specific except @@ -113,12 +133,12 @@ private: /// Live in values are typically arguments in registers. LiveIn values are /// allowed to have virtual registers associated with them, stored in the /// second element. - std::vector<std::pair<unsigned, unsigned> > LiveIns; + std::vector<std::pair<unsigned, unsigned>> LiveIns; - MachineRegisterInfo(const MachineRegisterInfo&) = delete; - void operator=(const MachineRegisterInfo&) = delete; public: explicit MachineRegisterInfo(MachineFunction *MF); + MachineRegisterInfo(const MachineRegisterInfo &) = delete; + MachineRegisterInfo &operator=(const MachineRegisterInfo &) = delete; const TargetRegisterInfo *getTargetRegisterInfo() const { return MF->getSubtarget().getRegisterInfo(); @@ -196,6 +216,23 @@ public: // Register Info //===--------------------------------------------------------------------===// + /// Returns true if the updated CSR list was initialized and false otherwise. + bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; } + + /// Disables the register from the list of CSRs. + /// I.e. the register will not appear as part of the CSR mask. + /// \see UpdatedCalleeSavedRegs. + void disableCalleeSavedRegister(unsigned Reg); + + /// Returns list of callee saved registers. + /// The function returns the updated CSR list (after taking into account + /// registers that are disabled from the CSR list). + const MCPhysReg *getCalleeSavedRegs() const; + + /// Sets the updated Callee Saved Registers list. + /// Notice that it will override ant previously disabled/saved CSRs. + void setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs); + // Strictly for use by MachineInstr.cpp. void addRegOperandToUseList(MachineOperand *MO); @@ -227,8 +264,6 @@ public: template<bool, bool, bool, bool, bool, bool> friend class defusechain_instr_iterator; - - /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified /// register. typedef defusechain_iterator<true,true,false,true,false,false> @@ -727,8 +762,6 @@ public: const BitVector &getUsedPhysRegsMask() const { return UsedPhysRegMask; } - void setUsedPhysRegMask(BitVector &Mask) { UsedPhysRegMask = Mask; } - //===--------------------------------------------------------------------===// // Reserved Register Info //===--------------------------------------------------------------------===// @@ -800,7 +833,7 @@ public: // Iteration support for the live-ins set. It's kept in sorted order // by register number. - typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator + typedef std::vector<std::pair<unsigned,unsigned>>::const_iterator livein_iterator; livein_iterator livein_begin() const { return LiveIns.begin(); } livein_iterator livein_end() const { return LiveIns.end(); } @@ -836,7 +869,10 @@ public: bool ByOperand, bool ByInstr, bool ByBundle> class defusechain_iterator : public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> { - MachineOperand *Op; + friend class MachineRegisterInfo; + + MachineOperand *Op = nullptr; + explicit defusechain_iterator(MachineOperand *op) : Op(op) { // If the first node isn't one we're interested in, advance to one that // we are interested in. @@ -847,7 +883,6 @@ public: advance(); } } - friend class MachineRegisterInfo; void advance() { assert(Op && "Cannot increment end iterator!"); @@ -868,13 +903,14 @@ public: Op = getNextOperandForReg(Op); } } + public: typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::reference reference; typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::pointer pointer; - defusechain_iterator() : Op(nullptr) {} + defusechain_iterator() = default; bool operator==(const defusechain_iterator &x) const { return Op == x.Op; @@ -939,7 +975,10 @@ public: bool ByOperand, bool ByInstr, bool ByBundle> class defusechain_instr_iterator : public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> { - MachineOperand *Op; + friend class MachineRegisterInfo; + + MachineOperand *Op = nullptr; + explicit defusechain_instr_iterator(MachineOperand *op) : Op(op) { // If the first node isn't one we're interested in, advance to one that // we are interested in. @@ -950,7 +989,6 @@ public: advance(); } } - friend class MachineRegisterInfo; void advance() { assert(Op && "Cannot increment end iterator!"); @@ -971,13 +1009,14 @@ public: Op = getNextOperandForReg(Op); } } + public: typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::reference reference; typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::pointer pointer; - defusechain_instr_iterator() : Op(nullptr) {} + defusechain_instr_iterator() = default; bool operator==(const defusechain_instr_iterator &x) const { return Op == x.Op; @@ -1029,10 +1068,12 @@ public: /// register. If Reg is physical, it must be a register unit (from /// MCRegUnitIterator). class PSetIterator { - const int *PSet; - unsigned Weight; + const int *PSet = nullptr; + unsigned Weight = 0; + public: - PSetIterator(): PSet(nullptr), Weight(0) {} + PSetIterator() = default; + PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) { const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); if (TargetRegisterInfo::isVirtualRegister(RegUnit)) { @@ -1047,6 +1088,7 @@ public: if (*PSet == -1) PSet = nullptr; } + bool isValid() const { return PSet; } unsigned getWeight() const { return Weight; } @@ -1066,6 +1108,6 @@ getPressureSets(unsigned RegUnit) const { return PSetIterator(RegUnit, this); } -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_MACHINEREGISTERINFO_H diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 81b8741fea27..6b2a16e1d36e 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -1,4 +1,4 @@ -//==- MachineScheduler.h - MachineInstr Scheduling Pass ----------*- C++ -*-==// +//===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -112,12 +112,12 @@ class ScheduleHazardRecognizer; /// MachineSchedContext provides enough context from the MachineScheduler pass /// for the target to instantiate a scheduler. struct MachineSchedContext { - MachineFunction *MF; - const MachineLoopInfo *MLI; - const MachineDominatorTree *MDT; - const TargetPassConfig *PassConfig; - AliasAnalysis *AA; - LiveIntervals *LIS; + MachineFunction *MF = nullptr; + const MachineLoopInfo *MLI = nullptr; + const MachineDominatorTree *MDT = nullptr; + const TargetPassConfig *PassConfig = nullptr; + AliasAnalysis *AA = nullptr; + LiveIntervals *LIS = nullptr; RegisterClassInfo *RegClassInfo; @@ -165,22 +165,21 @@ class ScheduleDAGMI; /// before building the DAG. struct MachineSchedPolicy { // Allow the scheduler to disable register pressure tracking. - bool ShouldTrackPressure; + bool ShouldTrackPressure = false; /// Track LaneMasks to allow reordering of independent subregister writes /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks() - bool ShouldTrackLaneMasks; + bool ShouldTrackLaneMasks = false; // Allow the scheduler to force top-down or bottom-up scheduling. If neither // is true, the scheduler runs in both directions and converges. - bool OnlyTopDown; - bool OnlyBottomUp; + bool OnlyTopDown = false; + bool OnlyBottomUp = false; // Disable heuristic that tries to fetch nodes from long dependency chains // first. - bool DisableLatencyHeuristic; + bool DisableLatencyHeuristic = false; - MachineSchedPolicy(): ShouldTrackPressure(false), ShouldTrackLaneMasks(false), - OnlyTopDown(false), OnlyBottomUp(false), DisableLatencyHeuristic(false) {} + MachineSchedPolicy() = default; }; /// MachineSchedStrategy - Interface to the scheduling algorithm used by @@ -232,6 +231,7 @@ public: /// When all predecessor dependencies have been resolved, free this node for /// top-down scheduling. virtual void releaseTopNode(SUnit *SU) = 0; + /// When all successor dependencies have been resolved, free this node for /// bottom-up scheduling. virtual void releaseBottomNode(SUnit *SU) = 0; @@ -261,24 +261,20 @@ protected: MachineBasicBlock::iterator CurrentBottom; /// Record the next node in a scheduled cluster. - const SUnit *NextClusterPred; - const SUnit *NextClusterSucc; + const SUnit *NextClusterPred = nullptr; + const SUnit *NextClusterSucc = nullptr; #ifndef NDEBUG /// The number of instructions scheduled so far. Used to cut off the /// scheduler at the point determined by misched-cutoff. - unsigned NumInstrsScheduled; + unsigned NumInstrsScheduled = 0; #endif + public: ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S, bool RemoveKillFlags) : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA), - LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU), - NextClusterPred(nullptr), NextClusterSucc(nullptr) { -#ifndef NDEBUG - NumInstrsScheduled = 0; -#endif - } + LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU) {} // Provide a vtable anchor ~ScheduleDAGMI() override; @@ -375,7 +371,7 @@ protected: /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees /// will be empty. - SchedDFSResult *DFSResult; + SchedDFSResult *DFSResult = nullptr; BitVector ScheduledTrees; MachineBasicBlock::iterator LiveRegionEnd; @@ -389,8 +385,8 @@ protected: PressureDiffs SUPressureDiffs; /// Register pressure in this region computed by initRegPressure. - bool ShouldTrackPressure; - bool ShouldTrackLaneMasks; + bool ShouldTrackPressure = false; + bool ShouldTrackLaneMasks = false; IntervalPressure RegPressure; RegPressureTracker RPTracker; @@ -409,16 +405,14 @@ protected: /// True if disconnected subregister components are already renamed. /// The renaming is only done on demand if lane masks are tracked. - bool DisconnectedComponentsRenamed; + bool DisconnectedComponentsRenamed = false; public: ScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S) : ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false), - RegClassInfo(C->RegClassInfo), DFSResult(nullptr), - ShouldTrackPressure(false), ShouldTrackLaneMasks(false), - RPTracker(RegPressure), TopRPTracker(TopPressure), - BotRPTracker(BotPressure), DisconnectedComponentsRenamed(false) {} + RegClassInfo(C->RegClassInfo), RPTracker(RegPressure), + TopRPTracker(TopPressure), BotRPTracker(BotPressure) {} ~ScheduleDAGMILive() override; @@ -573,6 +567,8 @@ struct SchedRemainder { // Unscheduled resources SmallVector<unsigned, 16> RemainingCounts; + SchedRemainder() { reset(); } + void reset() { CriticalPath = 0; CyclicCritPath = 0; @@ -581,8 +577,6 @@ struct SchedRemainder { RemainingCounts.clear(); } - SchedRemainder() { reset(); } - void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel); }; @@ -598,14 +592,14 @@ public: LogMaxQID = 2 }; - ScheduleDAGMI *DAG; - const TargetSchedModel *SchedModel; - SchedRemainder *Rem; + ScheduleDAGMI *DAG = nullptr; + const TargetSchedModel *SchedModel = nullptr; + SchedRemainder *Rem = nullptr; ReadyQueue Available; ReadyQueue Pending; - ScheduleHazardRecognizer *HazardRec; + ScheduleHazardRecognizer *HazardRec = nullptr; private: /// True if the pending Q should be checked/updated before scheduling another @@ -665,9 +659,7 @@ public: /// Pending queues extend the ready queues with the same ID and the /// PendingFlag set. SchedBoundary(unsigned ID, const Twine &Name): - DAG(nullptr), SchedModel(nullptr), Rem(nullptr), Available(ID, Name+".A"), - Pending(ID << LogMaxQID, Name+".P"), - HazardRec(nullptr) { + Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") { reset(); } @@ -781,11 +773,11 @@ public: /// Policy for scheduling the next instruction in the candidate's zone. struct CandPolicy { - bool ReduceLatency; - unsigned ReduceResIdx; - unsigned DemandResIdx; + bool ReduceLatency = false; + unsigned ReduceResIdx = 0; + unsigned DemandResIdx = 0; - CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {} + CandPolicy() = default; bool operator==(const CandPolicy &RHS) const { return ReduceLatency == RHS.ReduceLatency && @@ -800,12 +792,12 @@ public: /// Status of an instruction's critical resource consumption. struct SchedResourceDelta { // Count critical resources in the scheduled region required by SU. - unsigned CritResources; + unsigned CritResources = 0; // Count critical resources from another region consumed by SU. - unsigned DemandedResources; + unsigned DemandedResources = 0; - SchedResourceDelta(): CritResources(0), DemandedResources(0) {} + SchedResourceDelta() = default; bool operator==(const SchedResourceDelta &RHS) const { return CritResources == RHS.CritResources @@ -866,13 +858,12 @@ public: protected: const MachineSchedContext *Context; - const TargetSchedModel *SchedModel; - const TargetRegisterInfo *TRI; + const TargetSchedModel *SchedModel = nullptr; + const TargetRegisterInfo *TRI = nullptr; SchedRemainder Rem; - GenericSchedulerBase(const MachineSchedContext *C): - Context(C), SchedModel(nullptr), TRI(nullptr) {} + GenericSchedulerBase(const MachineSchedContext *C) : Context(C) {} void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, SchedBoundary *OtherZone); @@ -887,7 +878,7 @@ protected: class GenericScheduler : public GenericSchedulerBase { public: GenericScheduler(const MachineSchedContext *C): - GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"), + GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"), Bot(SchedBoundary::BotQID, "BotQ") {} void initPolicy(MachineBasicBlock::iterator Begin, @@ -929,7 +920,7 @@ public: void registerRoots() override; protected: - ScheduleDAGMILive *DAG; + ScheduleDAGMILive *DAG = nullptr; MachineSchedPolicy RegionPolicy; @@ -1033,9 +1024,6 @@ createStoreClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI); std::unique_ptr<ScheduleDAGMutation> -createMacroFusionDAGMutation(const TargetInstrInfo *TII); - -std::unique_ptr<ScheduleDAGMutation> createCopyConstrainDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI); diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 06db17abaed9..284f8c197607 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -49,54 +49,59 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/TargetSchedule.h" namespace llvm { -class InstrItineraryData; +class AnalysisUsage; class MachineBasicBlock; +class MachineFunction; class MachineInstr; class MachineLoop; class MachineLoopInfo; class MachineRegisterInfo; +struct MCSchedClassDesc; +class raw_ostream; class TargetInstrInfo; class TargetRegisterInfo; -class raw_ostream; class MachineTraceMetrics : public MachineFunctionPass { - const MachineFunction *MF; - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; - const MachineRegisterInfo *MRI; - const MachineLoopInfo *Loops; + const MachineFunction *MF = nullptr; + const TargetInstrInfo *TII = nullptr; + const TargetRegisterInfo *TRI = nullptr; + const MachineRegisterInfo *MRI = nullptr; + const MachineLoopInfo *Loops = nullptr; TargetSchedModel SchedModel; public: + friend class Ensemble; + friend class Trace; + class Ensemble; - class Trace; + static char ID; + MachineTraceMetrics(); + void getAnalysisUsage(AnalysisUsage&) const override; bool runOnMachineFunction(MachineFunction&) override; void releaseMemory() override; void verifyAnalysis() const override; - friend class Ensemble; - friend class Trace; - /// Per-basic block information that doesn't depend on the trace through the /// block. struct FixedBlockInfo { /// The number of non-trivial instructions in the block. /// Doesn't count PHI and COPY instructions that are likely to be removed. - unsigned InstrCount; + unsigned InstrCount = ~0u; /// True when the block contains calls. - bool HasCalls; + bool HasCalls = false; - FixedBlockInfo() : InstrCount(~0u), HasCalls(false) {} + FixedBlockInfo() = default; /// Returns true when resource information for this block has been computed. bool hasResources() const { return InstrCount != ~0u; } @@ -134,11 +139,11 @@ public: struct TraceBlockInfo { /// Trace predecessor, or NULL for the first block in the trace. /// Valid when hasValidDepth(). - const MachineBasicBlock *Pred; + const MachineBasicBlock *Pred = nullptr; /// Trace successor, or NULL for the last block in the trace. /// Valid when hasValidHeight(). - const MachineBasicBlock *Succ; + const MachineBasicBlock *Succ = nullptr; /// The block number of the head of the trace. (When hasValidDepth()). unsigned Head; @@ -148,16 +153,13 @@ public: /// Accumulated number of instructions in the trace above this block. /// Does not include instructions in this block. - unsigned InstrDepth; + unsigned InstrDepth = ~0u; /// Accumulated number of instructions in the trace below this block. /// Includes instructions in this block. - unsigned InstrHeight; + unsigned InstrHeight = ~0u; - TraceBlockInfo() : - Pred(nullptr), Succ(nullptr), - InstrDepth(~0u), InstrHeight(~0u), - HasValidInstrDepths(false), HasValidInstrHeights(false) {} + TraceBlockInfo() = default; /// Returns true if the depth resources have been computed from the trace /// above this block. @@ -199,10 +201,10 @@ public: // itinerary data. /// Instruction depths have been computed. This implies hasValidDepth(). - bool HasValidInstrDepths; + bool HasValidInstrDepths = false; /// Instruction heights have been computed. This implies hasValidHeight(). - bool HasValidInstrHeights; + bool HasValidInstrHeights = false; /// Critical path length. This is the number of cycles in the longest data /// dependency chain through the trace. This is only valid when both @@ -242,6 +244,7 @@ public: public: explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {} + void print(raw_ostream&) const; /// Compute the total number of instructions in the trace. @@ -300,11 +303,12 @@ public: /// strategy, for example 'minimum resource height'. There is one trace for /// every block in the function. class Ensemble { + friend class Trace; + SmallVector<TraceBlockInfo, 4> BlockInfo; DenseMap<const MachineInstr*, InstrCycles> Cycles; SmallVector<unsigned, 0> ProcResourceDepths; SmallVector<unsigned, 0> ProcResourceHeights; - friend class Trace; void computeTrace(const MachineBasicBlock*); void computeDepthResources(const MachineBasicBlock*); @@ -317,9 +321,11 @@ public: protected: MachineTraceMetrics &MTM; + + explicit Ensemble(MachineTraceMetrics*); + virtual const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) =0; virtual const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) =0; - explicit Ensemble(MachineTraceMetrics*); const MachineLoop *getLoopFor(const MachineBasicBlock*) const; const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const; const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const; @@ -328,7 +334,8 @@ public: public: virtual ~Ensemble(); - virtual const char *getName() const =0; + + virtual const char *getName() const = 0; void print(raw_ostream&) const; void invalidate(const MachineBasicBlock *MBB); void verify() const; @@ -394,6 +401,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, En.print(OS); return OS; } + } // end namespace llvm -#endif +#endif // LLVM_CODEGEN_MACHINETRACEMETRICS_H diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index de7064f07c3e..e4744fd5e260 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -23,14 +23,13 @@ namespace llvm { class Type; - /// MVT - Machine Value Type. Every type that is supported natively by some + /// Machine Value Type. Every type that is supported natively by some /// processor targeted by LLVM occurs here. This means that any legal value /// type can be represented by an MVT. class MVT { public: enum SimpleValueType : int8_t { - // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are - // considered extended value types. + // Simple value types less than zero are considered extended value types. INVALID_SIMPLE_VALUE_TYPE = -1, // If you change this numbering, you must change the values in @@ -141,37 +140,37 @@ class MVT { // This value must be a multiple of 32. MAX_ALLOWED_VALUETYPE = 96, - // Token - A value of type llvm::TokenTy + // A value of type llvm::TokenTy token = 120, - // Metadata - This is MDNode or MDString. + // This is MDNode or MDString. Metadata = 121, - // iPTRAny - An int value the size of the pointer of the current + // An int value the size of the pointer of the current // target to any address space. This must only be used internal to // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. iPTRAny = 122, - // vAny - A vector with any length and element size. This is used + // A vector with any length and element size. This is used // for intrinsics that have overloadings based on vector types. // This is only for tblgen's consumption! vAny = 123, - // fAny - Any floating-point or vector floating-point value. This is used + // Any floating-point or vector floating-point value. This is used // for intrinsics that have overloadings based on floating-point types. // This is only for tblgen's consumption! fAny = 124, - // iAny - An integer or vector integer value of any bit width. This is + // An integer or vector integer value of any bit width. This is // used for intrinsics that have overloadings based on integer bit widths. // This is only for tblgen's consumption! iAny = 125, - // iPTR - An int value the size of the pointer of the current + // An int value the size of the pointer of the current // target. This should only be used internal to tblgen! iPTR = 126, - // Any - Any type. This is used for intrinsics that have overloadings. + // Any type. This is used for intrinsics that have overloadings. // This is only for tblgen's consumption! Any = 127 }; @@ -188,13 +187,13 @@ class MVT { 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. + /// 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. + /// Return true if this is a FP or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && SimpleTy <= MVT::LAST_FP_VALUETYPE) || @@ -202,7 +201,7 @@ class MVT { SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE)); } - /// isInteger - Return true if this is an integer, or a vector integer type. + /// Return true if this is an integer or a vector integer type. bool isInteger() const { return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || @@ -210,41 +209,40 @@ class MVT { SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE)); } - /// isScalarInteger - Return true if this is an integer, not including - /// vectors. + /// Return true if this is an integer, not including vectors. bool isScalarInteger() const { return (SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE); } - /// isVector - Return true if this is a vector value type. + /// Return true if this is a vector value type. bool isVector() const { return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); } - /// is16BitVector - Return true if this is a 16-bit vector type. + /// Return true if this is a 16-bit vector type. bool is16BitVector() const { return (SimpleTy == MVT::v2i8 || SimpleTy == MVT::v1i16 || SimpleTy == MVT::v16i1); } - /// is32BitVector - Return true if this is a 32-bit vector type. + /// Return true if this is a 32-bit vector type. bool is32BitVector() const { - return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 || - SimpleTy == MVT::v1i32 || SimpleTy == MVT::v2f16 || - SimpleTy == MVT::v1f32); + return (SimpleTy == MVT::v32i1 || SimpleTy == MVT::v4i8 || + SimpleTy == MVT::v2i16 || SimpleTy == MVT::v1i32 || + SimpleTy == MVT::v2f16 || SimpleTy == MVT::v1f32); } - /// is64BitVector - Return true if this is a 64-bit vector type. + /// Return true if this is a 64-bit vector type. bool is64BitVector() const { - return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || - SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v4f16 || SimpleTy == MVT::v2f32 || - SimpleTy == MVT::v1f64); + return (SimpleTy == MVT::v64i1 || SimpleTy == MVT::v8i8 || + SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 || + SimpleTy == MVT::v1i64 || SimpleTy == MVT::v4f16 || + SimpleTy == MVT::v2f32 || SimpleTy == MVT::v1f64); } - /// is128BitVector - Return true if this is a 128-bit vector type. + /// Return true if this is a 128-bit vector type. bool is128BitVector() const { return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || @@ -252,14 +250,14 @@ class MVT { SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); } - /// is256BitVector - Return true if this is a 256-bit vector type. + /// Return true if this is a 256-bit vector type. bool is256BitVector() const { return (SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 || SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 || SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64); } - /// is512BitVector - Return true if this is a 512-bit vector type. + /// Return true if this is a 512-bit vector type. bool is512BitVector() const { return (SimpleTy == MVT::v16f32 || SimpleTy == MVT::v8f64 || SimpleTy == MVT::v512i1 || SimpleTy == MVT::v64i8 || @@ -267,34 +265,34 @@ class MVT { SimpleTy == MVT::v8i64); } - /// is1024BitVector - Return true if this is a 1024-bit vector type. + /// Return true if this is a 1024-bit vector type. bool is1024BitVector() const { return (SimpleTy == MVT::v1024i1 || SimpleTy == MVT::v128i8 || SimpleTy == MVT::v64i16 || SimpleTy == MVT::v32i32 || SimpleTy == MVT::v16i64); } - /// is2048BitVector - Return true if this is a 1024-bit vector type. + /// Return true if this is a 1024-bit vector type. bool is2048BitVector() const { return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 || SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64); } - /// isOverloaded - Return true if this is an overloaded type for TableGen. + /// Return true if this is an overloaded type for TableGen. bool isOverloaded() const { return (SimpleTy==MVT::Any || SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); } - /// isPow2VectorType - Returns true if the given vector is a power of 2. + /// Returns true if the given vector is a power of 2. bool isPow2VectorType() const { unsigned NElts = getVectorNumElements(); return !(NElts & (NElts - 1)); } - /// getPow2VectorType - Widens the length of the given vector MVT up to - /// the nearest power of 2 and returns that type. + /// Widens the length of the given vector MVT up to the nearest power of 2 + /// and returns that type. MVT getPow2VectorType() const { if (isPow2VectorType()) return *this; @@ -304,8 +302,7 @@ class MVT { return MVT::getVectorVT(getVectorElementType(), Pow2NElts); } - /// getScalarType - If this is a vector type, return the element type, - /// otherwise return this. + /// If this is a vector, return the element type, otherwise return this. MVT getScalarType() const { return isVector() ? getVectorElementType() : *this; } @@ -516,14 +513,14 @@ class MVT { return getScalarType().getSizeInBits(); } - /// getStoreSize - Return the number of bytes overwritten by a store - /// of the specified value type. + /// Return the number of bytes overwritten by a store of the specified value + /// type. unsigned getStoreSize() const { return (getSizeInBits() + 7) / 8; } - /// getStoreSizeInBits - Return the number of bits overwritten by a store - /// of the specified value type. + /// Return the number of bits overwritten by a store of the specified value + /// type. unsigned getStoreSizeInBits() const { return getStoreSize() * 8; } diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index bd74805a2397..d96b5eac4520 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -1,4 +1,4 @@ -//===-- Solution.h ------- PBQP Solution ------------------------*- C++ -*-===// +//===- Solution.h - PBQP Solution -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,8 +14,8 @@ #ifndef LLVM_CODEGEN_PBQP_SOLUTION_H #define LLVM_CODEGEN_PBQP_SOLUTION_H -#include "Graph.h" -#include "Math.h" +#include "llvm/CodeGen/PBQP/Graph.h" +#include <cassert> #include <map> namespace llvm { @@ -26,17 +26,17 @@ namespace PBQP { /// To get the selection for each node in the problem use the getSelection method. class Solution { private: - typedef std::map<GraphBase::NodeId, unsigned> SelectionsMap; SelectionsMap selections; - unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; + unsigned r0Reductions = 0; + unsigned r1Reductions = 0; + unsigned r2Reductions = 0; + unsigned rNReductions = 0; public: - /// \brief Initialise an empty solution. - Solution() - : r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} + Solution() = default; /// \brief Set the selection for a given node. /// @param nodeId Node id. @@ -53,10 +53,9 @@ namespace PBQP { assert(sItr != selections.end() && "No selection for node."); return sItr->second; } - }; -} // namespace PBQP -} // namespace llvm +} // end namespace PBQP +} // end namespace llvm #endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index a9fd301691d6..42299b529410 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -60,7 +60,9 @@ namespace llvm { /// as if it was just created. /// If EmitFallbackDiag is true, the pass will emit a /// DiagnosticInfoISelFallback for every MachineFunction it resets. - MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag); + /// If AbortOnFailedISel is true, abort compilation instead of resetting. + MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag, + bool AbortOnFailedISel); /// createCodeGenPreparePass - Transform the code to expose more pattern /// matching during instruction selection. @@ -79,6 +81,9 @@ namespace llvm { /// MachineDominanaceFrontier - This pass is a machine dominators analysis pass. extern char &MachineDominanceFrontierID; + /// MachineRegionInfo - This pass computes SESE regions for machine functions. + extern char &MachineRegionInfoPassID; + /// EdgeBundles analysis - Bundle machine CFG edges. extern char &EdgeBundlesID; @@ -284,6 +289,9 @@ namespace llvm { /// the target platform. extern char &XRayInstrumentationID; + /// This pass inserts FEntry calls + extern char &FEntryInserterID; + /// \brief This pass implements the "patchable-function" attribute. extern char &PatchableFunctionID; @@ -318,14 +326,6 @@ namespace llvm { /// ExpandISelPseudos - This pass expands pseudo-instructions. extern char &ExpandISelPseudosID; - /// createExecutionDependencyFixPass - This pass fixes execution time - /// problems with dependent instructions, such as switching execution - /// domains to match. - /// - /// The pass will examine instructions using and defining registers in RC. - /// - FunctionPass *createExecutionDependencyFixPass(const TargetRegisterClass *RC); - /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; @@ -397,6 +397,14 @@ namespace llvm { /// This pass frees the memory occupied by the MachineFunction. FunctionPass *createFreeMachineFunctionPass(); + + /// This pass combine basic blocks guarded by the same branch. + extern char &BranchCoalescingID; + + /// This pass performs outlining on machine instructions directly before + /// printing assembly. + ModulePass *createMachineOutlinerPass(); + } // End llvm namespace /// Target machine pass initializer for passes with dependencies. Use with @@ -413,7 +421,7 @@ namespace llvm { Registry.registerPass(*PI, true); \ return PI; \ } \ - LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \ + static llvm::once_flag Initialize##passName##PassFlag; \ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ llvm::call_once(Initialize##passName##PassFlag, \ initialize##passName##PassOnce, std::ref(Registry)); \ diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 2cad90bbb703..8872a5dc54a1 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -1,4 +1,4 @@ -//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===// +//===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,15 +16,28 @@ #ifndef LLVM_CODEGEN_REGALLOCPBQP_H #define LLVM_CODEGEN_REGALLOCPBQP_H -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Hashing.h" #include "llvm/CodeGen/PBQP/CostAllocator.h" +#include "llvm/CodeGen/PBQP/Graph.h" +#include "llvm/CodeGen/PBQP/Math.h" #include "llvm/CodeGen/PBQP/ReductionRules.h" -#include "llvm/CodeGen/PBQPRAConstraint.h" +#include "llvm/CodeGen/PBQP/Solution.h" #include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <limits> +#include <memory> #include <set> +#include <vector> namespace llvm { +class FunctionPass; +class LiveIntervals; +class MachineBlockFrequencyInfo; +class MachineFunction; class raw_ostream; namespace PBQP { @@ -37,15 +50,10 @@ inline unsigned getSpillOptionIdx() { return 0; } /// /// Keeps track of the number of infinities in each row and column. class MatrixMetadata { -private: - MatrixMetadata(const MatrixMetadata&); - void operator=(const MatrixMetadata&); public: MatrixMetadata(const Matrix& M) - : WorstRow(0), WorstCol(0), - UnsafeRows(new bool[M.getRows() - 1]()), + : UnsafeRows(new bool[M.getRows() - 1]()), UnsafeCols(new bool[M.getCols() - 1]()) { - unsigned* ColCounts = new unsigned[M.getCols() - 1](); for (unsigned i = 1; i < M.getRows(); ++i) { @@ -66,13 +74,17 @@ public: delete[] ColCounts; } + MatrixMetadata(const MatrixMetadata &) = delete; + MatrixMetadata &operator=(const MatrixMetadata &) = delete; + unsigned getWorstRow() const { return WorstRow; } unsigned getWorstCol() const { return WorstCol; } const bool* getUnsafeRows() const { return UnsafeRows.get(); } const bool* getUnsafeCols() const { return UnsafeCols.get(); } private: - unsigned WorstRow, WorstCol; + unsigned WorstRow = 0; + unsigned WorstCol = 0; std::unique_ptr<bool[]> UnsafeRows; std::unique_ptr<bool[]> UnsafeCols; }; @@ -80,17 +92,16 @@ private: /// \brief Holds a vector of the allowed physical regs for a vreg. class AllowedRegVector { friend hash_code hash_value(const AllowedRegVector &); -public: - AllowedRegVector() : NumOpts(0), Opts(nullptr) {} +public: + AllowedRegVector() = default; + AllowedRegVector(AllowedRegVector &&) = default; AllowedRegVector(const std::vector<unsigned> &OptVec) : NumOpts(OptVec.size()), Opts(new unsigned[NumOpts]) { std::copy(OptVec.begin(), OptVec.end(), Opts.get()); } - AllowedRegVector(AllowedRegVector &&) = default; - unsigned size() const { return NumOpts; } unsigned operator[](size_t I) const { return Opts[I]; } @@ -105,7 +116,7 @@ public: } private: - unsigned NumOpts; + unsigned NumOpts = 0; std::unique_ptr<unsigned[]> Opts; }; @@ -120,8 +131,8 @@ inline hash_code hash_value(const AllowedRegVector &OptRegs) { class GraphMetadata { private: typedef ValuePool<AllowedRegVector> AllowedRegVecPool; -public: +public: typedef AllowedRegVecPool::PoolRef AllowedRegVecRef; GraphMetadata(MachineFunction &MF, @@ -168,13 +179,7 @@ public: OptimallyReducible } ReductionState; - NodeMetadata() - : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), - VReg(0) -#ifndef NDEBUG - , everConservativelyAllocatable(false) -#endif - {} + NodeMetadata() = default; NodeMetadata(const NodeMetadata &Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), @@ -190,9 +195,8 @@ public: } } - NodeMetadata(NodeMetadata &&Other) = default; - - NodeMetadata& operator=(NodeMetadata &&Other) = default; + NodeMetadata(NodeMetadata &&) = default; + NodeMetadata& operator=(NodeMetadata &&) = default; void setVReg(unsigned VReg) { this->VReg = VReg; } unsigned getVReg() const { return VReg; } @@ -249,21 +253,22 @@ public: #endif private: - ReductionState RS; - unsigned NumOpts; - unsigned DeniedOpts; + ReductionState RS = Unprocessed; + unsigned NumOpts = 0; + unsigned DeniedOpts = 0; std::unique_ptr<unsigned[]> OptUnsafeEdges; - unsigned VReg; + unsigned VReg = 0; GraphMetadata::AllowedRegVecRef AllowedRegs; #ifndef NDEBUG - bool everConservativelyAllocatable; + bool everConservativelyAllocatable = false; #endif }; class RegAllocSolverImpl { private: typedef MDMatrix<MatrixMetadata> RAMatrix; + public: typedef PBQP::Vector RawVector; typedef PBQP::Matrix RawMatrix; @@ -296,6 +301,7 @@ public: "PBQP Graph should not contain single or zero-option nodes"); G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); } + void handleRemoveNode(NodeId NId) {} void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} @@ -342,7 +348,6 @@ public: } private: - void promote(NodeId NId, NodeMetadata& NMd) { if (G.getNodeDegree(NId) == 3) { // This node is becoming optimally reducible. @@ -474,6 +479,7 @@ private: class SpillCostComparator { public: SpillCostComparator(const Graph& G) : G(G) {} + bool operator()(NodeId N1Id, NodeId N2Id) { PBQPNum N1SC = G.getNodeCosts(N1Id)[0]; PBQPNum N2SC = G.getNodeCosts(N2Id)[0]; @@ -481,6 +487,7 @@ private: return G.getNodeDegree(N1Id) < G.getNodeDegree(N2Id); return N1SC < N2SC; } + private: const Graph& G; }; @@ -495,8 +502,9 @@ private: class PBQPRAGraph : public PBQP::Graph<RegAllocSolverImpl> { private: typedef PBQP::Graph<RegAllocSolverImpl> BaseT; + public: - PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} + PBQPRAGraph(GraphMetadata Metadata) : BaseT(std::move(Metadata)) {} /// @brief Dump this graph to dbgs(). void dump() const; @@ -517,13 +525,13 @@ inline Solution solve(PBQPRAGraph& G) { return RegAllocSolver.solve(); } -} // namespace RegAlloc -} // namespace PBQP +} // end namespace RegAlloc +} // end namespace PBQP /// @brief Create a PBQP register allocator instance. FunctionPass * createPBQPRegisterAllocator(char *customPassID = nullptr); -} // namespace llvm +} // end namespace llvm -#endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ +#endif // LLVM_CODEGEN_REGALLOCPBQP_H diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index d784dfbda7ec..355c9f9b2f1e 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -1,4 +1,4 @@ -//===-- RegisterClassInfo.h - Dynamic Register Class Info -*- C++ -*-------===// +//===- RegisterClassInfo.h - Dynamic Register Class Info --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,22 +19,25 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h" +#include <cassert> +#include <cstdint> +#include <memory> namespace llvm { class RegisterClassInfo { struct RCInfo { - unsigned Tag; - unsigned NumRegs; - bool ProperSubClass; - uint8_t MinCost; - uint16_t LastCostChange; + unsigned Tag = 0; + unsigned NumRegs = 0; + bool ProperSubClass = false; + uint8_t MinCost = 0; + uint16_t LastCostChange = 0; std::unique_ptr<MCPhysReg[]> Order; - RCInfo() - : Tag(0), NumRegs(0), ProperSubClass(false), MinCost(0), - LastCostChange(0) {} + RCInfo() = default; operator ArrayRef<MCPhysReg>() const { return makeArrayRef(Order.get(), NumRegs); @@ -46,17 +49,18 @@ class RegisterClassInfo { // Tag changes whenever cached information needs to be recomputed. An RCInfo // entry is valid when its tag matches. - unsigned Tag; + unsigned Tag = 0; - const MachineFunction *MF; - const TargetRegisterInfo *TRI; + const MachineFunction *MF = nullptr; + const TargetRegisterInfo *TRI = nullptr; // Callee saved registers of last MF. Assumed to be valid until the next // runOnFunction() call. - const MCPhysReg *CalleeSaved; + // Used only to determine if an update was made to CalleeSavedAliases. + const MCPhysReg *CalleeSavedRegs = nullptr; - // Map register number to CalleeSaved index + 1; - SmallVector<uint8_t, 4> CSRNum; + // Map register alias to the callee saved Register. + SmallVector<MCPhysReg, 4> CalleeSavedAliases; // Reserved registers in the current MF. BitVector Reserved; @@ -105,11 +109,11 @@ public: } /// getLastCalleeSavedAlias - Returns the last callee saved register that - /// overlaps PhysReg, or 0 if Reg doesn't overlap a CSR. + /// overlaps PhysReg, or 0 if Reg doesn't overlap a CalleeSavedAliases. unsigned getLastCalleeSavedAlias(unsigned PhysReg) const { assert(TargetRegisterInfo::isPhysicalRegister(PhysReg)); - if (unsigned N = CSRNum[PhysReg]) - return CalleeSaved[N-1]; + if (PhysReg < CalleeSavedAliases.size()) + return CalleeSavedAliases[PhysReg]; return 0; } @@ -140,6 +144,7 @@ public: protected: unsigned computePSetLimit(unsigned Idx) const; }; + } // end namespace llvm -#endif +#endif // LLVM_CODEGEN_REGISTERCLASSINFO_H diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 313be355e7d7..a3ea41d5236e 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -1,4 +1,4 @@ -//===-- RegisterPressure.h - Dynamic Register Pressure -*- C++ -*-------===// +//===- RegisterPressure.h - Dynamic Register Pressure -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,25 @@ #ifndef LLVM_CODEGEN_REGISTERPRESSURE_H #define LLVM_CODEGEN_REGISTERPRESSURE_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseSet.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/MC/LaneBitmask.h" #include "llvm/Target/TargetRegisterInfo.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <limits> +#include <vector> namespace llvm { class LiveIntervals; -class LiveRange; -class RegisterClassInfo; class MachineInstr; +class RegisterClassInfo; struct RegisterMaskPair { unsigned RegUnit; ///< Virtual register or register unit. @@ -91,12 +100,13 @@ struct RegionPressure : RegisterPressure { /// higher level assert that pressure is consistent within a region. We also /// effectively ignore dead defs which don't affect heuristics much. class PressureChange { - uint16_t PSetID; // ID+1. 0=Invalid. - int16_t UnitInc; + uint16_t PSetID = 0; // ID+1. 0=Invalid. + int16_t UnitInc = 0; + public: - PressureChange(): PSetID(0), UnitInc(0) {} - PressureChange(unsigned id): PSetID(id+1), UnitInc(0) { - assert(id < UINT16_MAX && "PSetID overflow."); + PressureChange() = default; + PressureChange(unsigned id): PSetID(id + 1) { + assert(id < std::numeric_limits<uint16_t>::max() && "PSetID overflow."); } bool isValid() const { return PSetID > 0; } @@ -105,8 +115,11 @@ public: assert(isValid() && "invalid PressureChange"); return PSetID - 1; } + // If PSetID is invalid, return UINT16_MAX to give it lowest priority. - unsigned getPSetOrMax() const { return (PSetID - 1) & UINT16_MAX; } + unsigned getPSetOrMax() const { + return (PSetID - 1) & std::numeric_limits<uint16_t>::max(); + } int getUnitInc() const { return UnitInc; } @@ -146,7 +159,7 @@ public: void addPressureChange(unsigned RegUnit, bool IsDec, const MachineRegisterInfo *MRI); - LLVM_DUMP_METHOD void dump(const TargetRegisterInfo &TRI) const; + void dump(const TargetRegisterInfo &TRI) const; }; /// List of registers defined and used by a machine instruction. @@ -182,11 +195,12 @@ public: /// Array of PressureDiffs. class PressureDiffs { - PressureDiff *PDiffArray; - unsigned Size; - unsigned Max; + PressureDiff *PDiffArray = nullptr; + unsigned Size = 0; + unsigned Max = 0; + public: - PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {} + PressureDiffs() = default; ~PressureDiffs() { free(PDiffArray); } void clear() { Size = 0; } @@ -200,6 +214,7 @@ public: const PressureDiff &operator[](unsigned Idx) const { return const_cast<PressureDiffs*>(this)->operator[](Idx); } + /// \brief Record pressure difference induced by the given operand list to /// node with index \p Idx. void addInstruction(unsigned Idx, const RegisterOperands &RegOpers, @@ -225,7 +240,7 @@ struct RegPressureDelta { PressureChange CriticalMax; PressureChange CurrentMax; - RegPressureDelta() {} + RegPressureDelta() = default; bool operator==(const RegPressureDelta &RHS) const { return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax @@ -264,6 +279,7 @@ private: assert(Reg < NumRegUnits); return Reg; } + unsigned getRegFromSparseIndex(unsigned SparseIndex) const { if (SparseIndex >= NumRegUnits) return TargetRegisterInfo::index2VirtReg(SparseIndex-NumRegUnits); @@ -338,14 +354,14 @@ public: /// tracking. Changing direction has the side effect of closing region, and /// traversing past TopIdx or BottomIdx reopens it. class RegPressureTracker { - const MachineFunction *MF; - const TargetRegisterInfo *TRI; - const RegisterClassInfo *RCI; + const MachineFunction *MF = nullptr; + const TargetRegisterInfo *TRI = nullptr; + const RegisterClassInfo *RCI = nullptr; const MachineRegisterInfo *MRI; - const LiveIntervals *LIS; + const LiveIntervals *LIS = nullptr; /// We currently only allow pressure tracking within a block. - const MachineBasicBlock *MBB; + const MachineBasicBlock *MBB = nullptr; /// Track the max pressure within the region traversed so far. RegisterPressure &P; @@ -355,10 +371,10 @@ class RegPressureTracker { bool RequireIntervals; /// True if UntiedDefs will be populated. - bool TrackUntiedDefs; + bool TrackUntiedDefs = false; /// True if lanemasks should be tracked. - bool TrackLaneMasks; + bool TrackLaneMasks = false; /// Register pressure corresponds to liveness before this instruction /// iterator. It may point to the end of the block or a DebugValue rather than @@ -377,13 +393,8 @@ class RegPressureTracker { std::vector<unsigned> LiveThruPressure; public: - RegPressureTracker(IntervalPressure &rp) : - MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), - RequireIntervals(true), TrackUntiedDefs(false), TrackLaneMasks(false) {} - - RegPressureTracker(RegionPressure &rp) : - MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), - RequireIntervals(false), TrackUntiedDefs(false), TrackLaneMasks(false) {} + RegPressureTracker(IntervalPressure &rp) : P(rp), RequireIntervals(true) {} + RegPressureTracker(RegionPressure &rp) : P(rp), RequireIntervals(false) {} void reset(); @@ -555,6 +566,7 @@ protected: void dumpRegSetPressure(ArrayRef<unsigned> SetPressure, const TargetRegisterInfo *TRI); + } // end namespace llvm -#endif +#endif // LLVM_CODEGEN_REGISTERPRESSURE_H diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 1b9232b90193..1f939e72e139 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -1,4 +1,4 @@ -//===-- RegisterScavenging.h - Machine register scavenging ------*- C++ -*-===// +//===- RegisterScavenging.h - Machine register scavenging -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,49 +19,49 @@ #define LLVM_CODEGEN_REGISTERSCAVENGING_H #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/LaneBitmask.h" namespace llvm { -class MachineRegisterInfo; -class TargetRegisterInfo; +class MachineInstr; class TargetInstrInfo; class TargetRegisterClass; +class TargetRegisterInfo; class RegScavenger { const TargetRegisterInfo *TRI; const TargetInstrInfo *TII; MachineRegisterInfo* MRI; - MachineBasicBlock *MBB; + MachineBasicBlock *MBB = nullptr; MachineBasicBlock::iterator MBBI; - unsigned NumRegUnits; + unsigned NumRegUnits = 0; /// True if RegScavenger is currently tracking the liveness of registers. - bool Tracking; + bool Tracking = false; /// Information on scavenged registers (held in a spill slot). struct ScavengedInfo { - ScavengedInfo(int FI = -1) : FrameIndex(FI), Reg(0), Restore(nullptr) {} + ScavengedInfo(int FI = -1) : FrameIndex(FI) {} /// A spill slot used for scavenging a register post register allocation. int FrameIndex; /// If non-zero, the specific register is currently being /// scavenged. That is, it is spilled to this scavenging stack slot. - unsigned Reg; + unsigned Reg = 0; /// The instruction that restores the scavenged register from stack. - const MachineInstr *Restore; + const MachineInstr *Restore = nullptr; }; /// A vector of information on scavenged registers. SmallVector<ScavengedInfo, 2> Scavenged; - /// The current state of each reg unit immediately before MBBI. - /// One bit per register unit. If bit is not set it means any - /// register containing that register unit is currently being used. - BitVector RegUnitsAvailable; + LiveRegUnits LiveUnits; // These BitVectors are only used internally to forward(). They are members // to avoid frequent reallocations. @@ -69,8 +69,7 @@ class RegScavenger { BitVector TmpRegUnits; public: - RegScavenger() - : MBB(nullptr), NumRegUnits(0), Tracking(false) {} + RegScavenger() = default; /// Start tracking liveness from the begin of basic block \p MBB. void enterBasicBlock(MachineBasicBlock &MBB); @@ -165,17 +164,18 @@ public: /// Tell the scavenger a register is used. void setRegUsed(unsigned Reg, LaneBitmask LaneMask = LaneBitmask::getAll()); + private: /// Returns true if a register is reserved. It is never "unused". bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); } /// setUsed / setUnused - Mark the state of one or a number of register units. /// - void setUsed(BitVector &RegUnits) { - RegUnitsAvailable.reset(RegUnits); + void setUsed(const BitVector &RegUnits) { + LiveUnits.addUnits(RegUnits); } - void setUnused(BitVector &RegUnits) { - RegUnitsAvailable |= RegUnits; + void setUnused(const BitVector &RegUnits) { + LiveUnits.removeUnits(RegUnits); } /// Processes the current instruction and fill the KillRegUnits and @@ -204,6 +204,6 @@ private: void setLiveInsUsed(const MachineBasicBlock &MBB); }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_REGISTERSCAVENGING_H diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index ed4e0bc8a4a1..99afd8c5c9ab 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -1,4 +1,4 @@ -//===------- llvm/CodeGen/ScheduleDAG.h - Common Base Class------*- C++ -*-===// +//===- llvm/CodeGen/ScheduleDAG.h - Common Base Class -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// // -// This file implements the ScheduleDAG class, which is used as the common -// base class for instruction schedulers. This encapsulates the scheduling DAG, -// which is shared between SelectionDAG and MachineInstr scheduling. +/// \file Implements the ScheduleDAG class, which is used as the common base +/// class for instruction schedulers. This encapsulates the scheduling DAG, +/// which is shared between SelectionDAG and MachineInstr scheduling. // //===----------------------------------------------------------------------===// @@ -18,33 +18,38 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetLowering.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <string> +#include <vector> namespace llvm { - class SUnit; - class MachineConstantPool; - class MachineFunction; - class MachineRegisterInfo; - class MachineInstr; - struct MCSchedClassDesc; - class TargetRegisterInfo; - class ScheduleDAG; - class SDNode; - class TargetInstrInfo; - class MCInstrDesc; - class TargetMachine; - class TargetRegisterClass; - template<class Graph> class GraphWriter; - - /// SDep - Scheduling dependency. This represents one direction of an - /// edge in the scheduling DAG. + +template<class Graph> class GraphWriter; +class MachineFunction; +class MachineRegisterInfo; +class MCInstrDesc; +struct MCSchedClassDesc; +class ScheduleDAG; +class SDNode; +class SUnit; +class TargetInstrInfo; +class TargetMachine; +class TargetRegisterClass; +class TargetRegisterInfo; + + /// Scheduling dependency. This represents one direction of an edge in the + /// scheduling DAG. class SDep { public: - /// Kind - These are the different kinds of scheduling dependencies. + /// These are the different kinds of scheduling dependencies. enum Kind { Data, ///< Regular data dependence (aka true-dependence). Anti, ///< A register anti-dependedence (aka WAR). @@ -71,33 +76,32 @@ namespace llvm { }; private: - /// Dep - A pointer to the depending/depended-on SUnit, and an enum + /// \brief A pointer to the depending/depended-on SUnit, and an enum /// indicating the kind of the dependency. PointerIntPair<SUnit *, 2, Kind> Dep; - /// Contents - A union discriminated by the dependence kind. + /// A union discriminated by the dependence kind. union { - /// Reg - For Data, Anti, and Output dependencies, the associated - /// register. For Data dependencies that don't currently have a register - /// assigned, this is set to zero. + /// For Data, Anti, and Output dependencies, the associated register. For + /// Data dependencies that don't currently have a register/ assigned, this + /// is set to zero. unsigned Reg; - /// Order - Additional information about Order dependencies. + /// Additional information about Order dependencies. unsigned OrdKind; // enum OrderKind } Contents; - /// Latency - The time associated with this edge. Often this is just - /// the value of the Latency field of the predecessor, however advanced - /// models may provide additional information about specific edges. + /// The time associated with this edge. Often this is just the value of the + /// Latency field of the predecessor, however advanced models may provide + /// additional information about specific edges. unsigned Latency; public: - /// SDep - Construct a null SDep. This is only for use by container - /// classes which require default constructors. SUnits may not - /// have null SDep edges. + /// Constructs a null SDep. This is only for use by container classes which + /// require default constructors. SUnits may not/ have null SDep edges. SDep() : Dep(nullptr, Data) {} - /// SDep - Construct an SDep with the specified values. + /// Constructs an SDep with the specified values. SDep(SUnit *S, Kind kind, unsigned Reg) : Dep(S, kind), Contents() { switch (kind) { @@ -116,12 +120,13 @@ namespace llvm { break; } } + SDep(SUnit *S, OrderKind kind) : Dep(S, Order), Contents(), Latency(0) { Contents.OrdKind = kind; } - /// Return true if the specified SDep is equivalent except for latency. + /// Returns true if the specified SDep is equivalent except for latency. bool overlaps(const SDep &Other) const; bool operator==(const SDep &Other) const { @@ -132,100 +137,95 @@ namespace llvm { return !operator==(Other); } - /// getLatency - Return the latency value for this edge, which roughly - /// means the minimum number of cycles that must elapse between the - /// predecessor and the successor, given that they have this edge - /// between them. + /// \brief Returns the latency value for this edge, which roughly means the + /// minimum number of cycles that must elapse between the predecessor and + /// the successor, given that they have this edge between them. unsigned getLatency() const { return Latency; } - /// setLatency - Set the latency for this edge. + /// Sets the latency for this edge. void setLatency(unsigned Lat) { Latency = Lat; } - //// getSUnit - Return the SUnit to which this edge points. + //// Returns the SUnit to which this edge points. SUnit *getSUnit() const; - //// setSUnit - Assign the SUnit to which this edge points. + //// Assigns the SUnit to which this edge points. void setSUnit(SUnit *SU); - /// getKind - Return an enum value representing the kind of the dependence. + /// Returns an enum value representing the kind of the dependence. Kind getKind() const; - /// isCtrl - Shorthand for getKind() != SDep::Data. + /// Shorthand for getKind() != SDep::Data. bool isCtrl() const { return getKind() != Data; } - /// isNormalMemory - Test if this is an Order dependence between two - /// memory accesses where both sides of the dependence access memory - /// in non-volatile and fully modeled ways. + /// \brief Tests if this is an Order dependence between two memory accesses + /// where both sides of the dependence access memory in non-volatile and + /// fully modeled ways. bool isNormalMemory() const { return getKind() == Order && (Contents.OrdKind == MayAliasMem || Contents.OrdKind == MustAliasMem); } - /// isBarrier - Test if this is an Order dependence that is marked - /// as a barrier. + /// Tests if this is an Order dependence that is marked as a barrier. bool isBarrier() const { return getKind() == Order && Contents.OrdKind == Barrier; } - /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory - /// dependence. + /// Tests 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. + /// \brief Tests 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. bool isMustAlias() const { return getKind() == Order && Contents.OrdKind == MustAliasMem; } - /// isWeak - Test if this a weak dependence. Weak dependencies are - /// considered DAG edges for height computation and other heuristics, but do - /// not force ordering. Breaking a weak edge may require the scheduler to - /// compensate, for example by inserting a copy. + /// Tests if this a weak dependence. Weak dependencies are considered DAG + /// edges for height computation and other heuristics, but do not force + /// ordering. Breaking a weak edge may require the scheduler to compensate, + /// for example by inserting a copy. bool isWeak() const { return getKind() == Order && Contents.OrdKind >= Weak; } - /// isArtificial - Test if this is an Order dependence that is marked - /// as "artificial", meaning it isn't necessary for correctness. + /// \brief Tests if this is an Order dependence that is marked as + /// "artificial", meaning it isn't necessary for correctness. bool isArtificial() const { return getKind() == Order && Contents.OrdKind == Artificial; } - /// isCluster - Test if this is an Order dependence that is marked - /// as "cluster", meaning it is artificial and wants to be adjacent. + /// \brief Tests if this is an Order dependence that is marked as "cluster", + /// meaning it is artificial and wants to be adjacent. bool isCluster() const { return getKind() == Order && Contents.OrdKind == Cluster; } - /// isAssignedRegDep - Test if this is a Data dependence that is - /// associated with a register. + /// Tests if this is a Data dependence that is associated with a register. bool isAssignedRegDep() const { return getKind() == Data && Contents.Reg != 0; } - /// getReg - Return the register associated with this edge. This is - /// only valid on Data, Anti, and Output edges. On Data edges, this - /// value may be zero, meaning there is no associated register. + /// Returns the register associated with this edge. This is only valid on + /// Data, Anti, and Output edges. On Data edges, this value may be zero, + /// meaning there is no associated register. unsigned getReg() const { assert((getKind() == Data || getKind() == Anti || getKind() == Output) && "getReg called on non-register dependence edge!"); return Contents.Reg; } - /// setReg - Assign the associated register for this edge. This is - /// only valid on Data, Anti, and Output edges. On Anti and Output - /// edges, this value must not be zero. On Data edges, the value may - /// be zero, which would mean that no specific register is associated - /// with this edge. + /// Assigns the associated register for this edge. This is only valid on + /// Data, Anti, and Output edges. On Anti and Output edges, this value must + /// not be zero. On Data edges, the value may be zero, which would mean that + /// no specific register is associated with this edge. void setReg(unsigned Reg) { assert((getKind() == Data || getKind() == Anti || getKind() == Output) && "setReg called on non-register dependence edge!"); @@ -240,115 +240,101 @@ namespace llvm { template <> struct isPodLike<SDep> { static const bool value = true; }; - /// SUnit - Scheduling unit. This is a node in the scheduling DAG. + /// Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: enum : unsigned { BoundaryID = ~0u }; - SDNode *Node; // Representative node. - MachineInstr *Instr; // Alternatively, a MachineInstr. + SDNode *Node = nullptr; ///< Representative node. + MachineInstr *Instr = nullptr; ///< Alternatively, a MachineInstr. + public: - SUnit *OrigNode; // If not this, the node from which - // this node was cloned. - // (SD scheduling only) + SUnit *OrigNode = nullptr; ///< If not this, the node from which this node + /// was cloned. (SD scheduling only) - const MCSchedClassDesc *SchedClass; // NULL or resolved SchedClass. + const MCSchedClassDesc *SchedClass = + nullptr; ///< nullptr or resolved SchedClass. - // Preds/Succs - The SUnits before/after us in the graph. - SmallVector<SDep, 4> Preds; // All sunit predecessors. - SmallVector<SDep, 4> Succs; // All sunit successors. + SmallVector<SDep, 4> Preds; ///< All sunit predecessors. + SmallVector<SDep, 4> Succs; ///< All sunit successors. typedef SmallVectorImpl<SDep>::iterator pred_iterator; typedef SmallVectorImpl<SDep>::iterator succ_iterator; typedef SmallVectorImpl<SDep>::const_iterator const_pred_iterator; typedef SmallVectorImpl<SDep>::const_iterator const_succ_iterator; - unsigned NodeNum; // Entry # of node in the node vector. - unsigned NodeQueueId; // Queue id of node. - unsigned NumPreds; // # of SDep::Data preds. - unsigned NumSuccs; // # of SDep::Data sucss. - unsigned NumPredsLeft; // # of preds not scheduled. - unsigned NumSuccsLeft; // # of succs not scheduled. - unsigned WeakPredsLeft; // # of weak preds not scheduled. - unsigned WeakSuccsLeft; // # of weak succs not scheduled. - unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use. - unsigned short Latency; // Node latency. - bool isVRegCycle : 1; // May use and def the same vreg. - bool isCall : 1; // Is a function call. - bool isCallOp : 1; // Is a function call operand. - bool isTwoAddress : 1; // Is a two-address instruction. - bool isCommutable : 1; // Is a commutable instruction. - bool hasPhysRegUses : 1; // Has physreg uses. - bool hasPhysRegDefs : 1; // Has physreg defs that are being used. - bool hasPhysRegClobbers : 1; // Has any physreg defs, used or not. - bool isPending : 1; // True once pending. - bool isAvailable : 1; // True once available. - bool isScheduled : 1; // True once scheduled. - bool isScheduleHigh : 1; // True if preferable to schedule high. - bool isScheduleLow : 1; // True if preferable to schedule low. - bool isCloned : 1; // True if this node has been cloned. - bool isUnbuffered : 1; // Uses an unbuffered resource. - bool hasReservedResource : 1; // Uses a reserved resource. - Sched::Preference SchedulingPref; // Scheduling preference. + unsigned NodeNum = BoundaryID; ///< Entry # of node in the node vector. + unsigned NodeQueueId = 0; ///< Queue id of node. + unsigned NumPreds = 0; ///< # of SDep::Data preds. + unsigned NumSuccs = 0; ///< # of SDep::Data sucss. + unsigned NumPredsLeft = 0; ///< # of preds not scheduled. + unsigned NumSuccsLeft = 0; ///< # of succs not scheduled. + unsigned WeakPredsLeft = 0; ///< # of weak preds not scheduled. + unsigned WeakSuccsLeft = 0; ///< # of weak succs not scheduled. + unsigned short NumRegDefsLeft = 0; ///< # of reg defs with no scheduled use. + unsigned short Latency = 0; ///< Node latency. + bool isVRegCycle : 1; ///< May use and def the same vreg. + bool isCall : 1; ///< Is a function call. + bool isCallOp : 1; ///< Is a function call operand. + bool isTwoAddress : 1; ///< Is a two-address instruction. + bool isCommutable : 1; ///< Is a commutable instruction. + bool hasPhysRegUses : 1; ///< Has physreg uses. + bool hasPhysRegDefs : 1; ///< Has physreg defs that are being used. + bool hasPhysRegClobbers : 1; ///< Has any physreg defs, used or not. + bool isPending : 1; ///< True once pending. + bool isAvailable : 1; ///< True once available. + bool isScheduled : 1; ///< True once scheduled. + bool isScheduleHigh : 1; ///< True if preferable to schedule high. + bool isScheduleLow : 1; ///< True if preferable to schedule low. + bool isCloned : 1; ///< True if this node has been cloned. + bool isUnbuffered : 1; ///< Uses an unbuffered resource. + bool hasReservedResource : 1; ///< Uses a reserved resource. + Sched::Preference SchedulingPref = Sched::None; ///< Scheduling preference. private: - bool isDepthCurrent : 1; // True if Depth is current. - bool isHeightCurrent : 1; // True if Height is current. - unsigned Depth; // Node depth. - unsigned Height; // Node height. + bool isDepthCurrent : 1; ///< True if Depth is current. + bool isHeightCurrent : 1; ///< True if Height is current. + unsigned Depth = 0; ///< Node depth. + unsigned Height = 0; ///< Node height. + public: - unsigned TopReadyCycle; // Cycle relative to start when node is ready. - unsigned BotReadyCycle; // Cycle relative to end when node is ready. + unsigned TopReadyCycle = 0; ///< Cycle relative to start when node is ready. + unsigned BotReadyCycle = 0; ///< Cycle relative to end when node is ready. - const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. - const TargetRegisterClass *CopySrcRC; + const TargetRegisterClass *CopyDstRC = + nullptr; ///< Is a special copy node if != nullptr. + const TargetRegisterClass *CopySrcRC = nullptr; - /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent - /// an SDNode and any nodes flagged to it. + /// \brief Constructs an SUnit for pre-regalloc scheduling to represent an + /// SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) - : Node(node), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr), - NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), - NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), - NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), + : Node(node), NodeNum(nodenum), isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isScheduleLow(false), isCloned(false), - isUnbuffered(false), hasReservedResource(false), - SchedulingPref(Sched::None), isDepthCurrent(false), - isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), - BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} + isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), + isHeightCurrent(false) {} - /// SUnit - Construct an SUnit for post-regalloc scheduling to represent - /// a MachineInstr. + /// \brief Constructs an SUnit for post-regalloc scheduling to represent a + /// MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) - : Node(nullptr), Instr(instr), OrigNode(nullptr), SchedClass(nullptr), - NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), - NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), - NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), + : Instr(instr), NodeNum(nodenum), isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isScheduleLow(false), isCloned(false), - isUnbuffered(false), hasReservedResource(false), - SchedulingPref(Sched::None), isDepthCurrent(false), - isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), - BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} + isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), + isHeightCurrent(false) {} - /// SUnit - Construct a placeholder SUnit. + /// \brief Constructs a placeholder SUnit. SUnit() - : Node(nullptr), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr), - NodeNum(BoundaryID), NodeQueueId(0), NumPreds(0), NumSuccs(0), - NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), - NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), - isCallOp(false), isTwoAddress(false), isCommutable(false), - hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), - isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isScheduleLow(false), isCloned(false), - isUnbuffered(false), hasReservedResource(false), - SchedulingPref(Sched::None), isDepthCurrent(false), - isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), - BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} + : isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), + isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), isPending(false), isAvailable(false), + isScheduled(false), isScheduleHigh(false), isScheduleLow(false), + isCloned(false), isUnbuffered(false), hasReservedResource(false), + isDepthCurrent(false), isHeightCurrent(false) {} /// \brief Boundary nodes are placeholders for the boundary of the /// scheduling region. @@ -359,46 +345,44 @@ namespace llvm { /// an assoicative data structure keyed on node ID. bool isBoundaryNode() const { return NodeNum == BoundaryID; } - /// setNode - Assign the representative SDNode for this SUnit. - /// This may be used during pre-regalloc scheduling. + /// Assigns the representative SDNode for this SUnit. This may be used + /// during pre-regalloc scheduling. void setNode(SDNode *N) { assert(!Instr && "Setting SDNode of SUnit with MachineInstr!"); Node = N; } - /// getNode - Return the representative SDNode for this SUnit. - /// This may be used during pre-regalloc scheduling. + /// Returns the representative SDNode for this SUnit. This may be used + /// during pre-regalloc scheduling. SDNode *getNode() const { assert(!Instr && "Reading SDNode of SUnit with MachineInstr!"); return Node; } - /// isInstr - Return true if this SUnit refers to a machine instruction as + /// \brief Returns true if this SUnit refers to a machine instruction as /// opposed to an SDNode. bool isInstr() const { return Instr; } - /// setInstr - Assign the instruction for the SUnit. - /// This may be used during post-regalloc scheduling. + /// Assigns the instruction for the SUnit. This may be used during + /// post-regalloc scheduling. void setInstr(MachineInstr *MI) { assert(!Node && "Setting MachineInstr of SUnit with SDNode!"); Instr = MI; } - /// getInstr - Return the representative MachineInstr for this SUnit. - /// This may be used during post-regalloc scheduling. + /// Returns the representative MachineInstr for this SUnit. This may be used + /// during post-regalloc scheduling. MachineInstr *getInstr() const { assert(!Node && "Reading MachineInstr of SUnit with SDNode!"); return Instr; } - /// addPred - This adds the specified edge as a pred of the current node if - /// not already. It also adds the current node as a successor of the - /// specified node. + /// Adds the specified edge as a pred of the current node if not already. + /// It also adds the current node as a successor of the specified node. bool addPred(const SDep &D, bool Required = true); - /// addPredBarrier - This adds a barrier edge to SU by calling - /// addPred(), with latency 0 generally or latency 1 for a store - /// followed by a load. + /// \brief Adds a barrier edge to SU by calling addPred(), with latency 0 + /// generally or latency 1 for a store followed by a load. bool addPredBarrier(SUnit *SU) { SDep Dep(SU, SDep::Barrier); unsigned TrueMemOrderLatency = @@ -407,20 +391,19 @@ namespace llvm { return addPred(Dep); } - /// removePred - This removes the specified edge as a pred of the current - /// node if it exists. It also removes the current node as a successor of - /// the specified node. + /// Removes the specified edge as a pred of the current node if it exists. + /// It also removes the current node as a successor of the specified node. void removePred(const SDep &D); - /// getDepth - Return the depth of this node, which is the length of the - /// maximum path up to any node which has no predecessors. + /// Returns the depth of this node, which is the length of the maximum path + /// up to any node which has no predecessors. unsigned getDepth() const { if (!isDepthCurrent) const_cast<SUnit *>(this)->ComputeDepth(); return Depth; } - /// getHeight - Return the height of this node, which is the length of the + /// \brief Returns the height of this node, which is the length of the /// maximum path down to any node which has no successors. unsigned getHeight() const { if (!isHeightCurrent) @@ -428,38 +411,36 @@ namespace llvm { return Height; } - /// setDepthToAtLeast - If NewDepth is greater than this node's - /// depth value, set it to be the new depth value. This also - /// recursively marks successor nodes dirty. + /// \brief If NewDepth is greater than this node's depth value, sets it to + /// be the new depth value. This also recursively marks successor nodes + /// dirty. void setDepthToAtLeast(unsigned NewDepth); - /// setDepthToAtLeast - If NewDepth is greater than this node's - /// depth value, set it to be the new height value. This also - /// recursively marks predecessor nodes dirty. + /// \brief If NewDepth is greater than this node's depth value, set it to be + /// the new height value. This also recursively marks predecessor nodes + /// dirty. void setHeightToAtLeast(unsigned NewHeight); - /// setDepthDirty - Set a flag in this node to indicate that its - /// stored Depth value will require recomputation the next time - /// getDepth() is called. + /// \brief Sets a flag in this node to indicate that its stored Depth value + /// will require recomputation the next time getDepth() is called. void setDepthDirty(); - /// setHeightDirty - Set a flag in this node to indicate that its - /// stored Height value will require recomputation the next time - /// getHeight() is called. + /// \brief Sets a flag in this node to indicate that its stored Height value + /// will require recomputation the next time getHeight() is called. void setHeightDirty(); - /// isPred - Test if node N is a predecessor of this node. - bool isPred(SUnit *N) { - for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) - if (Preds[i].getSUnit() == N) + /// Tests if node N is a predecessor of this node. + bool isPred(const SUnit *N) const { + for (const SDep &Pred : Preds) + if (Pred.getSUnit() == N) return true; return false; } - /// isSucc - Test if node N is a successor of this node. - bool isSucc(SUnit *N) { - for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) - if (Succs[i].getSUnit() == N) + /// Tests if node N is a successor of this node. + bool isSucc(const SUnit *N) const { + for (const SDep &Succ : Succs) + if (Succ.getSUnit() == N) return true; return false; } @@ -471,7 +452,7 @@ namespace llvm { return NumSuccsLeft == 0; } - /// \brief Order this node's predecessor edges such that the critical path + /// \brief Orders this node's predecessor edges such that the critical path /// edge occurs first. void biasCriticalPath(); @@ -484,7 +465,7 @@ namespace llvm { void ComputeHeight(); }; - /// Return true if the specified SDep is equivalent except for latency. + /// Returns true if the specified SDep is equivalent except for latency. inline bool SDep::overlaps(const SDep &Other) const { if (Dep != Other.Dep) return false; @@ -499,31 +480,33 @@ namespace llvm { llvm_unreachable("Invalid dependency kind!"); } - //// getSUnit - Return the SUnit to which this edge points. + //// Returns the SUnit to which this edge points. inline SUnit *SDep::getSUnit() const { return Dep.getPointer(); } - //// setSUnit - Assign the SUnit to which this edge points. + //// Assigns the SUnit to which this edge points. inline void SDep::setSUnit(SUnit *SU) { Dep.setPointer(SU); } - /// getKind - Return an enum value representing the kind of the dependence. + /// Returns an enum value representing the kind of the dependence. inline SDep::Kind SDep::getKind() const { return Dep.getInt(); } //===--------------------------------------------------------------------===// - /// SchedulingPriorityQueue - This interface is used to plug different - /// priorities computation algorithms into the list scheduler. It implements - /// the interface of a standard priority queue, where nodes are inserted in - /// arbitrary order and returned in priority order. The computation of the - /// priority and the representation of the queue are totally up to the - /// implementation to decide. - /// + + /// \brief This interface is used to plug different priorities computation + /// algorithms into the list scheduler. It implements the interface of a + /// standard priority queue, where nodes are inserted in arbitrary order and + /// returned in priority order. The computation of the priority and the + /// representation of the queue are totally up to the implementation to + /// decide. class SchedulingPriorityQueue { virtual void anchor(); - unsigned CurCycle; + + unsigned CurCycle = 0; bool HasReadyFilter; + public: - SchedulingPriorityQueue(bool rf = false): - CurCycle(0), HasReadyFilter(rf) {} - virtual ~SchedulingPriorityQueue() {} + SchedulingPriorityQueue(bool rf = false) : HasReadyFilter(rf) {} + + virtual ~SchedulingPriorityQueue() = default; virtual bool isBottomUp() const = 0; @@ -542,6 +525,7 @@ namespace llvm { assert(!HasReadyFilter && "The ready filter must override isReady()"); return true; } + virtual void push(SUnit *U) = 0; void push_all(const std::vector<SUnit *> &Nodes) { @@ -556,10 +540,9 @@ namespace llvm { virtual void dump(ScheduleDAG *) const {} - /// scheduledNode - As each node is scheduled, this method is invoked. This - /// allows the priority function to adjust the priority of related - /// unscheduled nodes, for example. - /// + /// As each node is scheduled, this method is invoked. This allows the + /// priority function to adjust the priority of related unscheduled nodes, + /// for example. virtual void scheduledNode(SUnit *) {} virtual void unscheduledNode(SUnit *) {} @@ -575,14 +558,14 @@ namespace llvm { class ScheduleDAG { public: - const TargetMachine &TM; // Target processor - const TargetInstrInfo *TII; // Target instruction information - const TargetRegisterInfo *TRI; // Target processor register info - MachineFunction &MF; // Machine function - MachineRegisterInfo &MRI; // Virtual/real register map - std::vector<SUnit> SUnits; // The scheduling units. - SUnit EntrySU; // Special node for the region entry. - SUnit ExitSU; // Special node for the region exit. + const TargetMachine &TM; ///< Target processor + const TargetInstrInfo *TII; ///< Target instruction information + const TargetRegisterInfo *TRI; ///< Target processor register info + MachineFunction &MF; ///< Machine function + MachineRegisterInfo &MRI; ///< Virtual/real register map + std::vector<SUnit> SUnits; ///< The scheduling units. + SUnit EntrySU; ///< Special node for the region entry. + SUnit ExitSU; ///< Special node for the region exit. #ifdef NDEBUG static const bool StressSched = false; @@ -594,43 +577,39 @@ namespace llvm { virtual ~ScheduleDAG(); - /// clearDAG - clear the DAG state (between regions). + /// Clears the DAG state (between regions). void clearDAG(); - /// getInstrDesc - Return the MCInstrDesc of this SUnit. - /// Return NULL for SDNodes without a machine opcode. + /// Returns the MCInstrDesc of this SUnit. + /// Returns NULL for SDNodes without a machine opcode. const MCInstrDesc *getInstrDesc(const SUnit *SU) const { if (SU->isInstr()) return &SU->getInstr()->getDesc(); return getNodeDesc(SU->getNode()); } - /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered - /// using 'dot'. - /// + /// Pops up a GraphViz/gv window with the ScheduleDAG rendered using 'dot'. virtual void viewGraph(const Twine &Name, const Twine &Title); virtual void viewGraph(); virtual void dumpNode(const SUnit *SU) const = 0; - /// getGraphNodeLabel - Return a label for an SUnit node in a visualization - /// of the ScheduleDAG. + /// Returns a label for an SUnit node in a visualization of the ScheduleDAG. virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0; - /// getDAGLabel - Return a label for the region of code covered by the DAG. + /// Returns a label for the region of code covered by the DAG. virtual std::string getDAGName() const = 0; - /// addCustomGraphFeatures - Add custom features for a visualization of - /// the ScheduleDAG. + /// Adds custom features for a visualization of the ScheduleDAG. virtual void addCustomGraphFeatures(GraphWriter<ScheduleDAG*> &) const {} #ifndef NDEBUG - /// VerifyScheduledDAG - Verify that all SUnits were scheduled and that - /// their state is consistent. Return the number of scheduled SUnits. + /// \brief Verifies that all SUnits were scheduled and that their state is + /// consistent. Returns the number of scheduled SUnits. unsigned VerifyScheduledDAG(bool isBottomUp); #endif private: - // Return the MCInstrDesc of this SDNode or NULL. + /// Returns the MCInstrDesc of this SDNode or NULL. const MCInstrDesc *getNodeDesc(const SDNode *Node) const; }; @@ -640,6 +619,7 @@ namespace llvm { unsigned Operand; SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {} + public: bool operator==(const SUnitIterator& x) const { return Operand == x.Operand; @@ -666,7 +646,8 @@ namespace llvm { unsigned getOperand() const { return Operand; } const SUnit *getNode() const { return Node; } - /// isCtrlDep - Test if this is not an SDep::Data dependence. + + /// Tests if this is not an SDep::Data dependence. bool isCtrlDep() const { return getSDep().isCtrl(); } @@ -700,56 +681,61 @@ namespace llvm { } }; - /// ScheduleDAGTopologicalSort is a class that computes a topological - /// ordering for SUnits and provides methods for dynamically updating - /// the ordering as new edges are added. + /// This class can compute a topological ordering for SUnits and provides + /// methods for dynamically updating the ordering as new edges are added. /// /// This allows a very fast implementation of IsReachable, for example. - /// class ScheduleDAGTopologicalSort { - /// SUnits - A reference to the ScheduleDAG's SUnits. + /// A reference to the ScheduleDAG's SUnits. std::vector<SUnit> &SUnits; SUnit *ExitSU; - /// Index2Node - Maps topological index to the node number. + /// Maps topological index to the node number. std::vector<int> Index2Node; - /// Node2Index - Maps the node number to its topological index. + /// Maps the node number to its topological index. std::vector<int> Node2Index; - /// Visited - a set of nodes visited during a DFS traversal. + /// a set of nodes visited during a DFS traversal. BitVector Visited; - /// DFS - make a DFS traversal and mark all nodes affected by the - /// edge insertion. These nodes will later get new topological indexes - /// by means of the Shift method. + /// Makes a DFS traversal and mark all nodes affected by the edge insertion. + /// These nodes will later get new topological indexes by means of the Shift + /// method. void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); - /// Shift - reassign topological indexes for the nodes in the DAG - /// to preserve the topological ordering. + /// \brief Reassigns topological indexes for the nodes in the DAG to + /// preserve the topological ordering. void Shift(BitVector& Visited, int LowerBound, int UpperBound); - /// Allocate - assign the topological index to the node n. + /// Assigns the topological index to the node n. void Allocate(int n, int index); public: ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits, SUnit *ExitSU); - /// InitDAGTopologicalSorting - create the initial topological - /// ordering from the DAG to be scheduled. + /// Creates the initial topological ordering from the DAG to be scheduled. void InitDAGTopologicalSorting(); - /// IsReachable - Checks if SU is reachable from TargetSU. + /// Returns an array of SUs that are both in the successor + /// subtree of StartSU and in the predecessor subtree of TargetSU. + /// StartSU and TargetSU are not in the array. + /// Success is false if TargetSU is not in the successor subtree of + /// StartSU, else it is true. + std::vector<int> GetSubGraph(const SUnit &StartSU, const SUnit &TargetSU, + bool &Success); + + /// Checks if \p SU is reachable from \p TargetSU. bool IsReachable(const SUnit *SU, const SUnit *TargetSU); - /// WillCreateCycle - Return true if addPred(TargetSU, SU) creates a cycle. + /// Returns true if addPred(TargetSU, SU) creates a cycle. bool WillCreateCycle(SUnit *TargetSU, SUnit *SU); - /// AddPred - Updates the topological ordering to accommodate an edge - /// to be added from SUnit X to SUnit Y. + /// \brief Updates the topological ordering to accommodate an edge to be + /// added from SUnit \p X to SUnit \p Y. void AddPred(SUnit *Y, SUnit *X); - /// RemovePred - Updates the topological ordering to accommodate an - /// an edge to be removed from the specified node N from the predecessors - /// of the current node M. + /// \brief Updates the topological ordering to accommodate an an edge to be + /// removed from the specified node \p N from the predecessors of the + /// current node \p M. void RemovePred(SUnit *M, SUnit *N); typedef std::vector<int>::iterator iterator; @@ -766,6 +752,7 @@ namespace llvm { reverse_iterator rend() { return Index2Node.rend(); } const_reverse_iterator rend() const { return Index2Node.rend(); } }; -} -#endif +} // end namespace llvm + +#endif // LLVM_CODEGEN_SCHEDULEDAG_H diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 2746765f6e45..21e1740aa6b8 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file implements the ScheduleDAGInstrs class, which implements -// scheduling for a MachineInstr-based dependency graph. +/// \file Implements the ScheduleDAGInstrs class, which implements scheduling +/// for a MachineInstr-based dependency graph. // //===----------------------------------------------------------------------===// @@ -95,8 +95,7 @@ namespace llvm { }; typedef SmallVector<UnderlyingObject, 4> UnderlyingObjectsVector; - /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of - /// MachineInstrs. + /// A ScheduleDAG for scheduling lists of MachineInstr. class ScheduleDAGInstrs : public ScheduleDAG { protected: const MachineLoopInfo *MLI; @@ -119,8 +118,8 @@ namespace llvm { /// Whether lane masks should get tracked. bool TrackLaneMasks; - /// State specific to the current scheduling region. - /// ------------------------------------------------ + // State specific to the current scheduling region. + // ------------------------------------------------ /// The block in which to insert instructions MachineBasicBlock *BB; @@ -138,8 +137,8 @@ namespace llvm { /// scheduling region is mapped to an SUnit. DenseMap<MachineInstr*, SUnit*> MISUnitMap; - /// State internal to DAG building. - /// ------------------------------- + // State internal to DAG building. + // ------------------------------- /// Defs, Uses - Remember where defs and uses of each register are as we /// iterate upward through the instructions. This is allocated here instead @@ -163,64 +162,64 @@ namespace llvm { SUnit *BarrierChain; public: - /// A list of SUnits, used in Value2SUsMap, during DAG construction. /// Note: to gain speed it might be worth investigating an optimized /// implementation of this data structure, such as a singly linked list /// with a memory pool (SmallVector was tried but slow and SparseSet is not /// applicable). typedef std::list<SUnit *> SUList; + protected: - /// A map from ValueType to SUList, used during DAG construction, - /// as a means of remembering which SUs depend on which memory - /// locations. + /// \brief A map from ValueType to SUList, used during DAG construction, as + /// a means of remembering which SUs depend on which memory locations. class Value2SUsMap; - /// Remove in FIFO order some SUs from huge maps. + /// Reduces maps in FIFO order, by N SUs. This is better than turning + /// every Nth memory SU into BarrierChain in buildSchedGraph(), since + /// it avoids unnecessary edges between seen SUs above the new BarrierChain, + /// and those below it. void reduceHugeMemNodeMaps(Value2SUsMap &stores, Value2SUsMap &loads, unsigned N); - /// Add a chain edge between SUa and SUb, but only if both AliasAnalysis - /// and Target fail to deny the dependency. + /// \brief Adds a chain edge between SUa and SUb, but only if both + /// AliasAnalysis and Target fail to deny the dependency. void addChainDependency(SUnit *SUa, SUnit *SUb, unsigned Latency = 0); - /// Add dependencies as needed from all SUs in list to SU. - void addChainDependencies(SUnit *SU, SUList &sus, unsigned Latency) { - for (auto *su : sus) - addChainDependency(SU, su, Latency); + /// Adds dependencies as needed from all SUs in list to SU. + void addChainDependencies(SUnit *SU, SUList &SUs, unsigned Latency) { + for (SUnit *Entry : SUs) + addChainDependency(SU, Entry, Latency); } - /// Add dependencies as needed from all SUs in map, to SU. + /// Adds dependencies as needed from all SUs in map, to SU. void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap); - /// Add dependencies as needed to SU, from all SUs mapped to V. + /// Adds dependencies as needed to SU, from all SUs mapped to V. void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap, ValueType V); - /// Add barrier chain edges from all SUs in map, and then clear - /// the map. This is equivalent to insertBarrierChain(), but - /// optimized for the common case where the new BarrierChain (a - /// global memory object) has a higher NodeNum than all SUs in - /// map. It is assumed BarrierChain has been set before calling - /// this. + /// Adds barrier chain edges from all SUs in map, and then clear the map. + /// This is equivalent to insertBarrierChain(), but optimized for the common + /// case where the new BarrierChain (a global memory object) has a higher + /// NodeNum than all SUs in map. It is assumed BarrierChain has been set + /// before calling this. void addBarrierChain(Value2SUsMap &map); - /// Insert a barrier chain in a huge region, far below current - /// SU. Add barrier chain edges from all SUs in map with higher - /// NodeNums than this new BarrierChain, and remove them from - /// map. It is assumed BarrierChain has been set before calling - /// this. + /// Inserts a barrier chain in a huge region, far below current SU. + /// Adds barrier chain edges from all SUs in map with higher NodeNums than + /// this new BarrierChain, and remove them from map. It is assumed + /// BarrierChain has been set before calling this. void insertBarrierChain(Value2SUsMap &map); /// For an unanalyzable memory access, this Value is used in maps. UndefValue *UnknownValue; - /// DbgValues - Remember instruction that precedes DBG_VALUE. + typedef std::vector<std::pair<MachineInstr *, MachineInstr *>> + DbgValueVector; + /// Remember instruction that precedes DBG_VALUE. /// These are generated by buildSchedGraph but persist so they can be /// referenced when emitting the final schedule. - typedef std::vector<std::pair<MachineInstr *, MachineInstr *> > - DbgValueVector; DbgValueVector DbgValues; MachineInstr *FirstDbgValue; @@ -234,81 +233,86 @@ namespace llvm { ~ScheduleDAGInstrs() override {} - /// \brief Get the machine model for instruction scheduling. + /// Gets the machine model for instruction scheduling. const TargetSchedModel *getSchedModel() const { return &SchedModel; } - /// \brief Resolve and cache a resolved scheduling class for an SUnit. + /// Resolves and cache a resolved scheduling class for an SUnit. const MCSchedClassDesc *getSchedClass(SUnit *SU) const { if (!SU->SchedClass && SchedModel.hasInstrSchedModel()) SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); return SU->SchedClass; } - /// begin - Return an iterator to the top of the current scheduling region. + /// Returns an iterator to the top of the current scheduling region. MachineBasicBlock::iterator begin() const { return RegionBegin; } - /// end - Return an iterator to the bottom of the current scheduling region. + /// Returns an iterator to the bottom of the current scheduling region. MachineBasicBlock::iterator end() const { return RegionEnd; } - /// newSUnit - Creates a new SUnit and return a ptr to it. + /// Creates a new SUnit and return a ptr to it. SUnit *newSUnit(MachineInstr *MI); - /// getSUnit - Return an existing SUnit for this MI, or NULL. + /// Returns an existing SUnit for this MI, or nullptr. SUnit *getSUnit(MachineInstr *MI) const; - /// startBlock - Prepare to perform scheduling in the given block. + /// Prepares to perform scheduling in the given block. virtual void startBlock(MachineBasicBlock *BB); - /// finishBlock - Clean up after scheduling in the given block. + /// Cleans up after scheduling in the given block. virtual void finishBlock(); - /// Initialize the scheduler state for the next scheduling region. + /// \brief Initialize the DAG and common scheduler state for a new + /// scheduling region. This does not actually create the DAG, only clears + /// it. The scheduling driver may call BuildSchedGraph multiple times per + /// scheduling region. virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs); - /// Notify that the scheduler has finished scheduling the current region. + /// Called when the scheduler has finished scheduling the current region. virtual void exitRegion(); - /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are - /// input. + /// Builds SUnits for the current region. + /// If \p RPTracker is non-null, compute register pressure as a side effect. + /// The DAG builder is an efficient place to do it because it already visits + /// operands. void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = nullptr, PressureDiffs *PDiffs = nullptr, LiveIntervals *LIS = nullptr, bool TrackLaneMasks = false); - /// addSchedBarrierDeps - Add dependencies from instructions in the current - /// list of instructions being scheduled to scheduling barrier. We want to - /// make sure instructions which define registers that are either used by - /// the terminator or are live-out are properly scheduled. This is - /// especially important when the definition latency of the return value(s) - /// are too high to be hidden by the branch or when the liveout registers - /// used by instructions in the fallthrough block. + /// \brief Adds dependencies from instructions in the current list of + /// instructions being scheduled to scheduling barrier. We want to make sure + /// instructions which define registers that are either used by the + /// terminator or are live-out are properly scheduled. This is especially + /// important when the definition latency of the return value(s) are too + /// high to be hidden by the branch or when the liveout registers used by + /// instructions in the fallthrough block. void addSchedBarrierDeps(); - /// schedule - Order nodes according to selected style, filling - /// in the Sequence member. + /// Orders nodes according to selected style. /// /// Typically, a scheduling algorithm will implement schedule() without /// overriding enterRegion() or exitRegion(). virtual void schedule() = 0; - /// finalizeSchedule - Allow targets to perform final scheduling actions at - /// the level of the whole MachineFunction. By default does nothing. + /// Allow targets to perform final scheduling actions at the level of the + /// whole MachineFunction. By default does nothing. virtual void finalizeSchedule() {} void dumpNode(const SUnit *SU) const override; - /// Return a label for a DAG node that points to an instruction. + /// Returns a label for a DAG node that points to an instruction. std::string getGraphNodeLabel(const SUnit *SU) const override; - /// Return a label for the region of code covered by the DAG. + /// Returns a label for the region of code covered by the DAG. std::string getDAGName() const override; - /// \brief Fix register kill flags that scheduling has made invalid. + /// Fixes register kill flags that scheduling has made invalid. void fixupKills(MachineBasicBlock *MBB); + protected: void initSUnits(); void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx); @@ -316,21 +320,22 @@ namespace llvm { void addVRegDefDeps(SUnit *SU, unsigned OperIdx); void addVRegUseDeps(SUnit *SU, unsigned OperIdx); - /// \brief PostRA helper for rewriting kill flags. + /// Initializes register live-range state for updating kills. + /// PostRA helper for rewriting kill flags. void startBlockForKills(MachineBasicBlock *BB); - /// \brief Toggle a register operand kill flag. + /// Toggles a register operand kill flag. /// /// Other adjustments may be made to the instruction if necessary. Return /// true if the operand has been deleted, false if not. - bool toggleKillFlag(MachineInstr *MI, MachineOperand &MO); + void toggleKillFlag(MachineInstr &MI, MachineOperand &MO); /// Returns a mask for which lanes get read/written by the given (register) /// machine operand. LaneBitmask getLaneMaskForMO(const MachineOperand &MO) const; }; - /// newSUnit - Creates a new SUnit and return a ptr to it. + /// Creates a new SUnit and return a ptr to it. inline SUnit *ScheduleDAGInstrs::newSUnit(MachineInstr *MI) { #ifndef NDEBUG const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0]; @@ -341,13 +346,13 @@ namespace llvm { return &SUnits.back(); } - /// getSUnit - Return an existing SUnit for this MI, or NULL. + /// Returns an existing SUnit for this MI, or nullptr. inline SUnit *ScheduleDAGInstrs::getSUnit(MachineInstr *MI) const { DenseMap<MachineInstr*, SUnit*>::const_iterator I = MISUnitMap.find(MI); if (I == MISUnitMap.end()) return nullptr; return I->second; } -} // namespace llvm +} // end namespace llvm #endif diff --git a/include/llvm/CodeGen/ScheduleDAGMutation.h b/include/llvm/CodeGen/ScheduleDAGMutation.h index 02fe2294815c..5c236427e0b8 100644 --- a/include/llvm/CodeGen/ScheduleDAGMutation.h +++ b/include/llvm/CodeGen/ScheduleDAGMutation.h @@ -1,4 +1,4 @@ -//==- ScheduleDAGMutation.h - MachineInstr Scheduling ------------*- C++ -*-==// +//===- ScheduleDAGMutation.h - MachineInstr Scheduling ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,16 +16,19 @@ #define LLVM_CODEGEN_SCHEDULEDAGMUTATION_H namespace llvm { - class ScheduleDAGInstrs; - /// Mutate the DAG as a postpass after normal DAG building. - class ScheduleDAGMutation { - virtual void anchor(); - public: - virtual ~ScheduleDAGMutation() {} +class ScheduleDAGInstrs; - virtual void apply(ScheduleDAGInstrs *DAG) = 0; - }; -} +/// Mutate the DAG as a postpass after normal DAG building. +class ScheduleDAGMutation { + virtual void anchor(); -#endif +public: + virtual ~ScheduleDAGMutation() = default; + + virtual void apply(ScheduleDAGInstrs *DAG) = 0; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_SCHEDULEDAGMUTATION_H diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h index b2108ad3bedb..c2013661cfff 100644 --- a/include/llvm/CodeGen/ScheduleDFS.h +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -14,16 +14,16 @@ #ifndef LLVM_CODEGEN_SCHEDULEDFS_H #define LLVM_CODEGEN_SCHEDULEDFS_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/ScheduleDAG.h" -#include "llvm/Support/DataTypes.h" #include <vector> +#include <cassert> +#include <cstdint> namespace llvm { class raw_ostream; -class IntEqClasses; -class ScheduleDAGInstrs; -class SUnit; /// \brief Represent the ILP of the subDAG rooted at a DAG node. /// @@ -75,18 +75,18 @@ class SchedDFSResult { /// interior node. Finally, it is set to a representative subtree ID during /// finalization. struct NodeData { - unsigned InstrCount; - unsigned SubtreeID; + unsigned InstrCount = 0; + unsigned SubtreeID = InvalidSubtreeID; - NodeData(): InstrCount(0), SubtreeID(InvalidSubtreeID) {} + NodeData() = default; }; /// \brief Per-Subtree data computed during DFS. struct TreeData { - unsigned ParentTreeID; - unsigned SubInstrCount; + unsigned ParentTreeID = InvalidSubtreeID; + unsigned SubInstrCount = 0; - TreeData(): ParentTreeID(InvalidSubtreeID), SubInstrCount(0) {} + TreeData() = default; }; /// \brief Record a connection between subtrees and the connection level. @@ -107,7 +107,7 @@ class SchedDFSResult { // For each subtree discovered during DFS, record its connections to other // subtrees. - std::vector<SmallVector<Connection, 4> > SubtreeConnections; + std::vector<SmallVector<Connection, 4>> SubtreeConnections; /// Cache the current connection level of each subtree. /// This mutable array is updated during scheduling. @@ -189,6 +189,6 @@ public: raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val); -} // namespace llvm +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_SCHEDULEDFS_H diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 214be2794ba3..ace4a2d836ca 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -29,10 +29,10 @@ protected: /// state. Important to restore the state after backtracking. Additionally, /// MaxLookAhead=0 identifies a fake recognizer, allowing the client to /// bypass virtual calls. Currently the PostRA scheduler ignores it. - unsigned MaxLookAhead; + unsigned MaxLookAhead = 0; public: - ScheduleHazardRecognizer(): MaxLookAhead(0) {} + ScheduleHazardRecognizer() = default; virtual ~ScheduleHazardRecognizer(); enum HazardType { @@ -117,6 +117,6 @@ public: } }; -} +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index e0c30fe4d82a..466ab532030c 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -17,8 +17,8 @@ #define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H #include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/Support/DataTypes.h" #include <cassert> +#include <cstddef> #include <cstring> namespace llvm { @@ -38,21 +38,25 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { // bottom-up scheduler, then the scoreboard cycles are the inverse of the // scheduler's cycles. class Scoreboard { - unsigned *Data; + unsigned *Data = nullptr; // The maximum number of cycles monitored by the Scoreboard. This // value is determined based on the target itineraries to ensure // that all hazards can be tracked. - size_t Depth; + size_t Depth = 0; + // Indices into the Scoreboard that represent the current cycle. - size_t Head; + size_t Head = 0; + public: - Scoreboard():Data(nullptr), Depth(0), Head(0) { } + Scoreboard() = default; + ~Scoreboard() { delete[] Data; } size_t getDepth() const { return Depth; } + unsigned& operator[](size_t idx) const { // Depth is expected to be a power-of-2. assert(Depth && !(Depth & (Depth - 1)) && @@ -93,10 +97,10 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { const ScheduleDAG *DAG; /// IssueWidth - Max issue per cycle. 0=Unknown. - unsigned IssueWidth; + unsigned IssueWidth = 0; /// IssueCount - Count instructions issued in this cycle. - unsigned IssueCount; + unsigned IssueCount = 0; Scoreboard ReservedScoreboard; Scoreboard RequiredScoreboard; @@ -119,6 +123,6 @@ public: void RecedeCycle() override; }; -} +} // end namespace llvm -#endif //!LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H +#endif // LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 54d0436e4ab8..6f0509543e7d 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -36,6 +36,7 @@ namespace llvm { class MachineConstantPoolValue; class MachineFunction; class MDNode; +class OptimizationRemarkEmitter; class SDDbgValue; class TargetLowering; class SelectionDAGTargetInfo; @@ -171,6 +172,10 @@ class SelectionDAG { LLVMContext *Context; CodeGenOpt::Level OptLevel; + /// The function-level optimization remark emitter. Used to emit remarks + /// whenever manipulating the DAG. + OptimizationRemarkEmitter *ORE; + /// The starting token. SDNode EntryNode; @@ -239,7 +244,7 @@ public: std::function<void(SDNode *, SDNode *)> Callback; DAGNodeDeletedListener(SelectionDAG &DAG, std::function<void(SDNode *, SDNode *)> Callback) - : DAGUpdateListener(DAG), Callback(Callback) {} + : DAGUpdateListener(DAG), Callback(std::move(Callback)) {} void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); } }; @@ -318,7 +323,7 @@ public: ~SelectionDAG(); /// Prepare this SelectionDAG to process code in the given MachineFunction. - void init(MachineFunction &mf); + void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE); /// Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -331,6 +336,7 @@ public: const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } + OptimizationRemarkEmitter &getORE() const { return *ORE; } /// Pop up a GraphViz/gv window with the DAG rendered using 'dot'. void viewGraph(const std::string &Title); @@ -480,6 +486,13 @@ public: bool isTarget = false, bool isOpaque = false); SDValue getConstant(const APInt &Val, const SDLoc &DL, EVT VT, bool isTarget = false, bool isOpaque = false); + + SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget = false, + bool IsOpaque = false) { + return getConstant(APInt::getAllOnesValue(VT.getScalarSizeInBits()), DL, + VT, IsTarget, IsOpaque); + } + SDValue getConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT, bool isTarget = false, bool isOpaque = false); SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, @@ -733,6 +746,9 @@ public: return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops); } + /// Return true if the result of this operation is always undefined. + bool isUndef(unsigned Opcode, ArrayRef<SDValue> Ops); + /// Return an UNDEF node. UNDEF does not have a useful SDLoc. SDValue getUNDEF(EVT VT) { return getNode(ISD::UNDEF, SDLoc(), VT); @@ -1274,6 +1290,19 @@ public: void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne, const APInt &DemandedElts, unsigned Depth = 0) const; + /// Used to represent the possible overflow behavior of an operation. + /// Never: the operation cannot overflow. + /// Always: the operation will always overflow. + /// Sometime: the operation may or may not overflow. + enum OverflowKind { + OFK_Never, + OFK_Sometime, + OFK_Always, + }; + + /// Determine if the result of the addition of 2 node can overflow. + OverflowKind computeOverflowKind(SDValue N0, SDValue N1) const; + /// Test if the given value is known to have exactly one bit set. This differs /// from computeKnownBits in that it doesn't necessarily determine which bit /// is set. @@ -1288,6 +1317,17 @@ public: /// target nodes to be understood. unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; + /// Return the number of times the sign bit of the register is replicated into + /// the other bits. We know that at least 1 bit is always equal to the sign + /// bit (itself), but other cases can give us information. For example, + /// immediately after an "SRA X, 2", we know that the top 3 bits are all equal + /// to each other, so we return 3. The DemandedElts argument allows + /// us to only collect the minimum sign bits of the requested vector elements. + /// Targets can implement the ComputeNumSignBitsForTarget method in the + /// TargetLowering class to allow target nodes to be understood. + unsigned ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, + unsigned Depth = 0) const; + /// Return true if the specified operand is an ISD::ADD with a ConstantSDNode /// on the right-hand side, or if it is an ISD::OR with a ConstantSDNode that /// is guaranteed to have the same semantics as an ADD. This handles the diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 61d7ec4ecf5b..591b2f773344 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -20,6 +20,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/Pass.h" #include "llvm/Target/TargetSubtargetInfo.h" +#include <memory> namespace llvm { class FastISel; @@ -29,6 +30,7 @@ namespace llvm { class MachineBasicBlock; class MachineFunction; class MachineInstr; + class OptimizationRemarkEmitter; class TargetLowering; class TargetLibraryInfo; class FunctionLoweringInfo; @@ -53,6 +55,12 @@ public: CodeGenOpt::Level OptLevel; const TargetInstrInfo *TII; const TargetLowering *TLI; + bool FastISelFailed; + SmallPtrSet<const Instruction *, 4> ElidedArgCopyInstrs; + + /// Current optimization remark emitter. + /// Used to report things like combines and FastISel failures. + std::unique_ptr<OptimizationRemarkEmitter> ORE; static char ID; @@ -151,7 +159,9 @@ public: OPC_MorphNodeTo, // Space-optimized forms that implicitly encode number of result VTs. OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2, - OPC_CompleteMatch + OPC_CompleteMatch, + // Contains offset in table for pattern being selected + OPC_Coverage }; enum { @@ -213,6 +223,15 @@ protected: void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, const SDLoc &DL); + /// getPatternForIndex - Patterns selected by tablegen during ISEL + virtual StringRef getPatternForIndex(unsigned index) { + llvm_unreachable("Tblgen should generate the implementation of this!"); + } + + /// getIncludePathForIndex - get the td source location of pattern instantiation + virtual StringRef getIncludePathForIndex(unsigned index) { + llvm_unreachable("Tblgen should generate the implementation of this!"); + } public: // Calls to these predicates are generated by tblgen. bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS, @@ -270,6 +289,8 @@ private: SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, ArrayRef<SDValue> Ops, unsigned EmitNodeInfo); + SDNode *MutateStrictFPToFP(SDNode *Node, unsigned NewOpc); + /// Prepares the landing pad to take incoming values or do other EH /// personality specific tasks. Returns true if the block should be /// instruction selected, false if no code should be emitted for it. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index b6f5424dbbd7..81cc0b39cf87 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ---*- C++ -*-===// +//===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -118,11 +118,11 @@ namespace ISD { class SDValue { friend struct DenseMapInfo<SDValue>; - SDNode *Node; // The node defining the value we are using. - unsigned ResNo; // Which return value of the node we are using. + SDNode *Node = nullptr; // The node defining the value we are using. + unsigned ResNo = 0; // Which return value of the node we are using. public: - SDValue() : Node(nullptr), ResNo(0) {} + SDValue() = default; SDValue(SDNode *node, unsigned resno); /// get the index which selects a specific result in the SDNode @@ -250,16 +250,16 @@ class SDUse { /// Val - The value being used. SDValue Val; /// User - The user of this value. - SDNode *User; + SDNode *User = nullptr; /// Prev, Next - Pointers to the uses list of the SDNode referred by /// this operand. - SDUse **Prev, *Next; - - SDUse(const SDUse &U) = delete; - void operator=(const SDUse &U) = delete; + SDUse **Prev = nullptr; + SDUse *Next = nullptr; public: - SDUse() : User(nullptr), Prev(nullptr), Next(nullptr) {} + SDUse() = default; + SDUse(const SDUse &U) = delete; + SDUse &operator=(const SDUse &) = delete; /// Normally SDUse will just implicitly convert to an SDValue that it holds. operator const SDValue&() const { return Val; } @@ -350,20 +350,15 @@ private: bool NoSignedZeros : 1; bool AllowReciprocal : 1; bool VectorReduction : 1; + bool AllowContract : 1; public: /// Default constructor turns off all optimization flags. - SDNodeFlags() { - NoUnsignedWrap = false; - NoSignedWrap = false; - Exact = false; - UnsafeAlgebra = false; - NoNaNs = false; - NoInfs = false; - NoSignedZeros = false; - AllowReciprocal = false; - VectorReduction = false; - } + SDNodeFlags() + : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false), + UnsafeAlgebra(false), NoNaNs(false), NoInfs(false), + NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false), + AllowContract(false) {} // These are mutators for each flag. void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; } @@ -375,6 +370,7 @@ public: void setNoSignedZeros(bool b) { NoSignedZeros = b; } void setAllowReciprocal(bool b) { AllowReciprocal = b; } void setVectorReduction(bool b) { VectorReduction = b; } + void setAllowContract(bool b) { AllowContract = b; } // These are accessors for each flag. bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } @@ -386,6 +382,7 @@ public: bool hasNoSignedZeros() const { return NoSignedZeros; } bool hasAllowReciprocal() const { return AllowReciprocal; } bool hasVectorReduction() const { return VectorReduction; } + bool hasAllowContract() const { return AllowContract; } /// Clear any flags in this flag set that aren't also set in Flags. void intersectWith(const SDNodeFlags *Flags) { @@ -397,6 +394,8 @@ public: NoInfs &= Flags->NoInfs; NoSignedZeros &= Flags->NoSignedZeros; AllowReciprocal &= Flags->AllowReciprocal; + VectorReduction &= Flags->VectorReduction; + AllowContract &= Flags->AllowContract; } }; @@ -446,6 +445,7 @@ protected: class LSBaseSDNodeBitfields { friend class LSBaseSDNode; + uint16_t : NumMemSDNodeBits; uint16_t AddressingMode : 3; // enum ISD::MemIndexedMode @@ -493,21 +493,26 @@ protected: static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide"); private: + friend class SelectionDAG; + // TODO: unfriend HandleSDNode once we fix its operand handling. + friend class HandleSDNode; + /// Unique id per SDNode in the DAG. - int NodeId; + int NodeId = -1; /// The values that are used by this operation. - SDUse *OperandList; + SDUse *OperandList = nullptr; /// The types of the values this node defines. SDNode's may /// define multiple values simultaneously. const EVT *ValueList; /// List of uses for this SDNode. - SDUse *UseList; + SDUse *UseList = nullptr; /// The number of entries in the Operand/Value list. - unsigned short NumOperands, NumValues; + unsigned short NumOperands = 0; + unsigned short NumValues; // The ordering of the SDNodes. It roughly corresponds to the ordering of the // original LLVM instructions. @@ -522,10 +527,6 @@ private: /// Return a pointer to the specified value type. static const EVT *getValueTypeList(EVT VT); - friend class SelectionDAG; - // TODO: unfriend HandleSDNode once we fix its operand handling. - friend class HandleSDNode; - public: /// Unique and persistent id per SDNode in the DAG. /// Used for debug printing. @@ -616,10 +617,10 @@ public: /// operands that use a specific SDNode. class use_iterator : public std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t> { - SDUse *Op; - friend class SDNode; + SDUse *Op = nullptr; + explicit use_iterator(SDUse *op) : Op(op) {} public: @@ -628,8 +629,8 @@ public: typedef std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t>::pointer pointer; + use_iterator() = default; use_iterator(const use_iterator &I) : Op(I.Op) {} - use_iterator() : Op(nullptr) {} bool operator==(const use_iterator &x) const { return Op == x.Op; @@ -737,11 +738,15 @@ public: return false; } + /// Return true if all the users of N are contained in Nodes. + /// NOTE: Requires at least one match, but doesn't require them all. + static bool areOnlyUsersOf(ArrayRef<const SDNode *> Nodes, const SDNode *N); + /// Return the number of values used by this operation. unsigned getNumOperands() const { return NumOperands; } /// Helper method returns the integer value of a ConstantSDNode operand. - uint64_t getConstantOperandVal(unsigned Num) const; + inline uint64_t getConstantOperandVal(unsigned Num) const; const SDValue &getOperand(unsigned Num) const { assert(Num < NumOperands && "Invalid child # of SDNode!"); @@ -896,9 +901,8 @@ protected: /// SDNodes are created without any operands, and never own the operand /// storage. To add operands, see SelectionDAG::createOperands. SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) - : NodeType(Opc), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), - UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order), - debugLoc(std::move(dl)) { + : NodeType(Opc), ValueList(VTs.VTs), NumValues(VTs.NumVTs), + IROrder(Order), debugLoc(std::move(dl)) { memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits)); assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && @@ -1366,10 +1370,10 @@ public: }; class ConstantSDNode : public SDNode { - const ConstantInt *Value; - friend class SelectionDAG; + const ConstantInt *Value; + ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, const DebugLoc &DL, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL, @@ -1396,11 +1400,15 @@ public: } }; -class ConstantFPSDNode : public SDNode { - const ConstantFP *Value; +uint64_t SDNode::getConstantOperandVal(unsigned Num) const { + return cast<ConstantSDNode>(getOperand(Num))->getZExtValue(); +} +class ConstantFPSDNode : public SDNode { friend class SelectionDAG; + const ConstantFP *Value; + ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL, @@ -1471,10 +1479,12 @@ ConstantSDNode *isConstOrConstSplat(SDValue V); ConstantFPSDNode *isConstOrConstSplatFP(SDValue V); class GlobalAddressSDNode : public SDNode { + friend class SelectionDAG; + const GlobalValue *TheGlobal; int64_t Offset; unsigned char TargetFlags; - friend class SelectionDAG; + GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, const GlobalValue *GA, EVT VT, int64_t o, unsigned char TargetFlags); @@ -1495,10 +1505,10 @@ public: }; class FrameIndexSDNode : public SDNode { - int FI; - friend class SelectionDAG; + int FI; + FrameIndexSDNode(int fi, EVT VT, bool isTarg) : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, 0, DebugLoc(), getSDVTList(VT)), FI(fi) { @@ -1514,11 +1524,11 @@ public: }; class JumpTableSDNode : public SDNode { + friend class SelectionDAG; + int JTI; unsigned char TargetFlags; - friend class SelectionDAG; - JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF) : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, 0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { @@ -1535,6 +1545,8 @@ public: }; class ConstantPoolSDNode : public SDNode { + friend class SelectionDAG; + union { const Constant *ConstVal; MachineConstantPoolValue *MachineCPVal; @@ -1543,8 +1555,6 @@ class ConstantPoolSDNode : public SDNode { unsigned Alignment; // Minimum alignment requirement of CP (not log2 value). unsigned char TargetFlags; - friend class SelectionDAG; - ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, unsigned Align, unsigned char TF) : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, @@ -1598,12 +1608,12 @@ public: /// Completely target-dependent object reference. class TargetIndexSDNode : public SDNode { + friend class SelectionDAG; + unsigned char TargetFlags; int Index; int64_t Offset; - friend class SelectionDAG; - public: TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned char TF) : SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)), @@ -1619,10 +1629,10 @@ public: }; class BasicBlockSDNode : public SDNode { - MachineBasicBlock *MBB; - friend class SelectionDAG; + MachineBasicBlock *MBB; + /// Debug info is meaningful and potentially useful here, but we create /// blocks out of order when they're jumped to, which makes it a bit /// harder. Let's see if we need it first. @@ -1640,10 +1650,10 @@ public: /// A "pseudo-class" with methods for operating on BUILD_VECTORs. class BuildVectorSDNode : public SDNode { +public: // These are constructed as SDNodes and then cast to BuildVectorSDNodes. explicit BuildVectorSDNode() = delete; -public: /// Check if this is a constant splat, and if so, find the /// smallest element size that splats the vector. If MinSplatBits is /// nonzero, the element size must be at least that large. Note that the @@ -1700,10 +1710,10 @@ public: /// in the LLVM IR representation. /// class SrcValueSDNode : public SDNode { - const Value *V; - friend class SelectionDAG; + const Value *V; + /// Create a SrcValue for a general value. explicit SrcValueSDNode(const Value *v) : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} @@ -1718,10 +1728,10 @@ public: }; class MDNodeSDNode : public SDNode { - const MDNode *MD; - friend class SelectionDAG; + const MDNode *MD; + explicit MDNodeSDNode(const MDNode *md) : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) {} @@ -1735,10 +1745,10 @@ public: }; class RegisterSDNode : public SDNode { - unsigned Reg; - friend class SelectionDAG; + unsigned Reg; + RegisterSDNode(unsigned reg, EVT VT) : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) {} @@ -1751,11 +1761,11 @@ public: }; class RegisterMaskSDNode : public SDNode { + friend class SelectionDAG; + // The memory for RegMask is not owned by the node. const uint32_t *RegMask; - friend class SelectionDAG; - RegisterMaskSDNode(const uint32_t *mask) : SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)), RegMask(mask) {} @@ -1769,12 +1779,12 @@ public: }; class BlockAddressSDNode : public SDNode { + friend class SelectionDAG; + const BlockAddress *BA; int64_t Offset; unsigned char TargetFlags; - friend class SelectionDAG; - BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, int64_t o, unsigned char Flags) : SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)), @@ -1793,10 +1803,10 @@ public: }; class EHLabelSDNode : public SDNode { - MCSymbol *Label; - friend class SelectionDAG; + MCSymbol *Label; + EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L) : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {} @@ -1809,11 +1819,11 @@ public: }; class ExternalSymbolSDNode : public SDNode { + friend class SelectionDAG; + const char *Symbol; unsigned char TargetFlags; - friend class SelectionDAG; - ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, 0, DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) {} @@ -1829,9 +1839,10 @@ public: }; class MCSymbolSDNode : public SDNode { + friend class SelectionDAG; + MCSymbol *Symbol; - friend class SelectionDAG; MCSymbolSDNode(MCSymbol *Symbol, EVT VT) : SDNode(ISD::MCSymbol, 0, DebugLoc(), getSDVTList(VT)), Symbol(Symbol) {} @@ -1844,10 +1855,10 @@ public: }; class CondCodeSDNode : public SDNode { - ISD::CondCode Condition; - friend class SelectionDAG; + ISD::CondCode Condition; + explicit CondCodeSDNode(ISD::CondCode Cond) : SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)), Condition(Cond) {} @@ -1863,10 +1874,10 @@ public: /// This class is used to represent EVT's, which are used /// to parameterize some operations. class VTSDNode : public SDNode { - EVT ValueType; - friend class SelectionDAG; + EVT ValueType; + explicit VTSDNode(EVT VT) : SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)), ValueType(VT) {} @@ -1995,6 +2006,7 @@ public: class MaskedLoadSDNode : public MaskedLoadStoreSDNode { public: friend class SelectionDAG; + MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, ISD::LoadExtType ETy, bool IsExpanding, EVT MemVT, MachineMemOperand *MMO) @@ -2114,11 +2126,11 @@ private: friend class SelectionDAG; MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs) - : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {} + : SDNode(Opc, Order, DL, VTs) {} /// Memory reference descriptions for this instruction. - mmo_iterator MemRefs; - mmo_iterator MemRefsEnd; + mmo_iterator MemRefs = nullptr; + mmo_iterator MemRefsEnd = nullptr; public: mmo_iterator memoperands_begin() const { return MemRefs; } @@ -2184,9 +2196,11 @@ template <> struct GraphTraits<SDNode*> { typedef SDNodeIterator ChildIteratorType; static NodeRef getEntryNode(SDNode *N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { return SDNodeIterator::begin(N); } + static ChildIteratorType child_end(NodeRef N) { return SDNodeIterator::end(N); } diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 2ac3b3d86cb6..14fc3a499a08 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -602,19 +602,15 @@ namespace llvm { return newIndex; } - /// Remove the given machine instruction from the mapping. - void removeMachineInstrFromMaps(MachineInstr &MI) { - // remove index -> MachineInstr and - // MachineInstr -> index mappings - Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI); - if (mi2iItr != mi2iMap.end()) { - IndexListEntry *miEntry(mi2iItr->second.listEntry()); - assert(miEntry->getInstr() == &MI && "Instruction indexes broken."); - // FIXME: Eventually we want to actually delete these indexes. - miEntry->setInstr(nullptr); - mi2iMap.erase(mi2iItr); - } - } + /// Removes machine instruction (bundle) \p MI from the mapping. + /// This should be called before MachineInstr::eraseFromParent() is used to + /// remove a whole bundle or an unbundled instruction. + void removeMachineInstrFromMaps(MachineInstr &MI); + + /// Removes a single machine instruction \p MI from the mapping. + /// This should be called before MachineInstr::eraseFromBundle() is used to + /// remove a single instruction (out of a bundle). + void removeSingleMachineInstrFromMaps(MachineInstr &MI); /// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in /// maps used by register allocator. \returns the index where the new diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 7b55b7968635..a18936feea7b 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -1,4 +1,4 @@ -//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// +//===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,7 +13,11 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/MC/MCSymbol.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/Support/Debug.h" +#include <algorithm> +#include <cassert> +#include <cstdint> #include <vector> namespace llvm { @@ -21,6 +25,9 @@ namespace llvm { class AsmPrinter; class MCExpr; class MCStreamer; +class MCSymbol; +class raw_ostream; +class TargetRegisterInfo; /// \brief MI-level stackmap operands. /// @@ -189,21 +196,22 @@ public: Constant, ConstantIndex }; - LocationType Type; - unsigned Size; - unsigned Reg; - int64_t Offset; - Location() : Type(Unprocessed), Size(0), Reg(0), Offset(0) {} + LocationType Type = Unprocessed; + unsigned Size = 0; + unsigned Reg = 0; + int64_t Offset = 0; + + Location() = default; Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset) : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {} }; struct LiveOutReg { - unsigned short Reg; - unsigned short DwarfRegNum; - unsigned short Size; + unsigned short Reg = 0; + unsigned short DwarfRegNum = 0; + unsigned short Size = 0; - LiveOutReg() : Reg(0), DwarfRegNum(0), Size(0) {} + LiveOutReg() = default; LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum, unsigned short Size) : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {} @@ -245,18 +253,20 @@ private: typedef MapVector<uint64_t, uint64_t> ConstantPool; struct FunctionInfo { - uint64_t StackSize; - uint64_t RecordCount; - FunctionInfo() : StackSize(0), RecordCount(1) {} - explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize), RecordCount(1) {} + uint64_t StackSize = 0; + uint64_t RecordCount = 1; + + FunctionInfo() = default; + explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize) {} }; struct CallsiteInfo { - const MCExpr *CSOffsetExpr; - uint64_t ID; + const MCExpr *CSOffsetExpr = nullptr; + uint64_t ID = 0; LocationVec Locations; LiveOutVec LiveOuts; - CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} + + CallsiteInfo() = default; CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, LocationVec &&Locations, LiveOutVec &&LiveOuts) : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), @@ -309,6 +319,7 @@ private: void print(raw_ostream &OS); void debug() { print(dbgs()); } }; -} -#endif +} // end namespace llvm + +#endif // LLVM_CODEGEN_STACKMAPS_H diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h index 1b3c0eb4a4d0..0655f19a323e 100644 --- a/include/llvm/CodeGen/StackProtector.h +++ b/include/llvm/CodeGen/StackProtector.h @@ -1,4 +1,4 @@ -//===-- StackProtector.h - Stack Protector Insertion ----------------------===// +//===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,8 +23,10 @@ #include "llvm/IR/ValueMap.h" #include "llvm/Pass.h" #include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" namespace llvm { + class Function; class Module; class PHINode; @@ -48,11 +50,11 @@ public: typedef ValueMap<const AllocaInst *, SSPLayoutKind> SSPLayoutMap; private: - const TargetMachine *TM; + const TargetMachine *TM = nullptr; /// TLI - Keep a pointer of a TargetLowering to consult for determining /// target type sizes. - const TargetLoweringBase *TLI; + const TargetLoweringBase *TLI = nullptr; const Triple Trip; Function *F; @@ -67,7 +69,7 @@ private: /// \brief The minimum size of buffers that will receive stack smashing /// protection when -fstack-protection is used. - unsigned SSPBufferSize; + unsigned SSPBufferSize = 0; /// VisitedPHIs - The set of PHI nodes visited when determining /// if a variable's reference has been taken. This set @@ -111,12 +113,13 @@ private: public: static char ID; // Pass identification, replacement for typeid. - StackProtector() - : FunctionPass(ID), TM(nullptr), TLI(nullptr), SSPBufferSize(0) { + + StackProtector() : FunctionPass(ID) { initializeStackProtectorPass(*PassRegistry::getPassRegistry()); } + StackProtector(const TargetMachine *TM) - : FunctionPass(ID), TM(TM), TLI(nullptr), Trip(TM->getTargetTriple()), + : FunctionPass(ID), TM(TM), Trip(TM->getTargetTriple()), SSPBufferSize(8) { initializeStackProtectorPass(*PassRegistry::getPassRegistry()); } @@ -134,6 +137,7 @@ public: bool runOnFunction(Function &Fn) override; }; + } // end namespace llvm #endif // LLVM_CODEGEN_STACKPROTECTOR_H diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index cc71fa3918a1..adf2b3ea1c9b 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -1,4 +1,4 @@ -//==-- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info -*- C++ -*-==// +//==- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -15,24 +15,22 @@ #ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H #define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H +#include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/SectionKind.h" #include "llvm/Target/TargetLoweringObjectFile.h" namespace llvm { - class MachineModuleInfo; - class Mangler; - class MCAsmInfo; - class MCSection; - class MCSectionMachO; - class MCSymbol; - class MCContext; - class GlobalValue; - class TargetMachine; +class GlobalValue; +class MachineModuleInfo; +class Mangler; +class MCContext; +class MCSection; +class MCSymbol; +class TargetMachine; class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { - bool UseInitArray; + bool UseInitArray = false; mutable unsigned NextUniqueID = 1; // ID 0 is reserved for execute-only sections protected: @@ -40,9 +38,8 @@ protected: MCSymbolRefExpr::VK_None; public: - TargetLoweringObjectFileELF() : UseInitArray(false) {} - - ~TargetLoweringObjectFileELF() override {} + TargetLoweringObjectFileELF() = default; + ~TargetLoweringObjectFileELF() override = default; void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM, const MCSymbol *Sym) const override; @@ -89,12 +86,10 @@ public: const TargetMachine &TM) const override; }; - - class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { public: - ~TargetLoweringObjectFileMachO() override {} TargetLoweringObjectFileMachO(); + ~TargetLoweringObjectFileMachO() override = default; void Initialize(MCContext &Ctx, const TargetMachine &TM) override; @@ -135,13 +130,11 @@ public: const TargetMachine &TM) const override; }; - - class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { mutable unsigned NextUniqueID = 0; public: - ~TargetLoweringObjectFileCOFF() override {} + ~TargetLoweringObjectFileCOFF() override = default; void Initialize(MCContext &Ctx, const TargetMachine &TM) override; MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, @@ -171,6 +164,29 @@ public: const GlobalValue *GV) const override; }; +class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile { + mutable unsigned NextUniqueID = 0; + +public: + TargetLoweringObjectFileWasm() = default; + ~TargetLoweringObjectFileWasm() override = default; + + MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + + MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; + + void InitializeWasm(); + + const MCExpr *lowerRelativeReference(const GlobalValue *LHS, + const GlobalValue *RHS, + const TargetMachine &TM) const override; +}; + } // end namespace llvm -#endif +#endif // LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h index 2287f9aca4bf..f0c826dc1d45 100644 --- a/include/llvm/CodeGen/TargetPassConfig.h +++ b/include/llvm/CodeGen/TargetPassConfig.h @@ -115,6 +115,10 @@ protected: /// Default setting for -enable-tail-merge on this target. bool EnableTailMerge; + /// Require processing of functions such that callees are generated before + /// callers. + bool RequireCodeGenSCCOrder; + public: TargetPassConfig(TargetMachine *tm, PassManagerBase &pm); // Dummy constructor. @@ -162,6 +166,11 @@ public: bool getEnableTailMerge() const { return EnableTailMerge; } void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); } + bool requiresCodeGenSCCOrder() const { return RequireCodeGenSCCOrder; } + void setRequiresCodeGenSCCOrder(bool Enable = true) { + setOpt(RequireCodeGenSCCOrder, Enable); + } + /// Allow the target to override a specific pass without overriding the pass /// pipeline. When passes are added to the standard pipeline at the /// point where StandardID is expected, add TargetID in its place. @@ -286,6 +295,10 @@ public: /// verification is enabled. void addVerifyPass(const std::string &Banner); + /// Check whether or not GlobalISel should be enabled by default. + /// Fallback/abort behavior is controlled via other methods. + virtual bool isGlobalISelEnabled() const; + /// Check whether or not GlobalISel should abort on error. /// When this is disable, GlobalISel will fall back on SDISel instead of /// erroring out. diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 81054aba066f..1992412120aa 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/TargetSchedule.h - Sched Machine Model -----*- C++ -*-===// +//===- llvm/CodeGen/TargetSchedule.h - Sched Machine Model ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,10 +23,8 @@ namespace llvm { -class TargetRegisterInfo; -class TargetSubtargetInfo; -class TargetInstrInfo; class MachineInstr; +class TargetInstrInfo; /// Provide an instruction scheduling machine model to CodeGen passes. class TargetSchedModel { @@ -34,8 +32,8 @@ class TargetSchedModel { // processor. MCSchedModel SchedModel; InstrItineraryData InstrItins; - const TargetSubtargetInfo *STI; - const TargetInstrInfo *TII; + const TargetSubtargetInfo *STI = nullptr; + const TargetInstrInfo *TII = nullptr; SmallVector<unsigned, 16> ResourceFactors; unsigned MicroOpFactor; // Multiply to normalize microops to resource units. @@ -44,7 +42,7 @@ class TargetSchedModel { unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const; public: - TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {} + TargetSchedModel() : SchedModel(MCSchedModel::GetDefaultSchedModel()) {} /// \brief Initialize the machine model for instruction scheduling. /// @@ -93,6 +91,13 @@ public: /// \brief Maximum number of micro-ops that may be scheduled per cycle. unsigned getIssueWidth() const { return SchedModel.IssueWidth; } + /// \brief Return true if new group must begin. + bool mustBeginGroup(const MachineInstr *MI, + const MCSchedClassDesc *SC = nullptr) const; + /// \brief Return true if current group must end. + bool mustEndGroup(const MachineInstr *MI, + const MCSchedClassDesc *SC = nullptr) const; + /// \brief Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC = nullptr) const; @@ -178,13 +183,18 @@ public: bool UseDefaultDefLatency = true) const; unsigned computeInstrLatency(unsigned Opcode) const; + /// \brief Output dependency latency of a pair of defs of the same register. /// /// This is typically one cycle. unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *DepMI) const; + + /// \brief Compute the reciprocal throughput of the given instruction. + Optional<double> computeInstrRThroughput(const MachineInstr *MI) const; + Optional<double> computeInstrRThroughput(unsigned Opcode) const; }; -} // namespace llvm +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_TARGETSCHEDULE_H diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index 2699fa28f0f1..0a3063663cef 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -25,9 +25,9 @@ namespace llvm { class LLVMContext; class Type; - /// EVT - Extended Value Type. Capable of holding value types which are not - /// native for any processor (such as the i12345 type), as well as the types - /// a MVT can represent. + /// Extended Value Type. Capable of holding value types which are not native + /// for any processor (such as the i12345 type), as well as the types an MVT + /// can represent. struct EVT { private: MVT V; @@ -49,15 +49,15 @@ namespace llvm { return false; } - /// getFloatingPointVT - Returns the EVT that represents a floating point - /// type with the given number of bits. There are two floating point types - /// with 128 bits - this returns f128 rather than ppcf128. + /// Returns the EVT that represents a floating-point type with the given + /// number of bits. There are two floating-point types with 128 bits - this + /// returns f128 rather than ppcf128. static EVT getFloatingPointVT(unsigned BitWidth) { return MVT::getFloatingPointVT(BitWidth); } - /// getIntegerVT - Returns the EVT that represents an integer with the given - /// number of bits. + /// Returns the EVT that represents an integer with the given number of + /// bits. static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) { MVT M = MVT::getIntegerVT(BitWidth); if (M.SimpleTy >= 0) @@ -65,8 +65,8 @@ namespace llvm { return getExtendedIntegerVT(Context, BitWidth); } - /// getVectorVT - Returns the EVT that represents a vector NumElements in - /// length, where each element is of type VT. + /// Returns the EVT that represents a vector NumElements in length, where + /// each element is of type VT. static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) { MVT M = MVT::getVectorVT(VT.V, NumElements); if (M.SimpleTy >= 0) @@ -74,9 +74,9 @@ namespace llvm { return getExtendedVectorVT(Context, VT, NumElements); } - /// changeVectorElementTypeToInteger - Return a vector with the same number - /// of elements as this vector, but with the element type converted to an - /// integer type with the same bitwidth. + /// Return a vector with the same number of elements as this vector, but + /// with the element type converted to an integer type with the same + /// bitwidth. EVT changeVectorElementTypeToInteger() const { if (!isSimple()) return changeExtendedVectorElementTypeToInteger(); @@ -102,140 +102,136 @@ namespace llvm { return changeExtendedTypeToInteger(); } - /// isSimple - Test if the given EVT is simple (as opposed to being - /// extended). + /// Test if the given EVT is simple (as opposed to being extended). bool isSimple() const { return V.SimpleTy >= 0; } - /// isExtended - Test if the given EVT is extended (as opposed to - /// being simple). + /// Test if the given EVT is extended (as opposed to being simple). bool isExtended() const { return !isSimple(); } - /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + /// Return true if this is a FP or a vector FP type. bool isFloatingPoint() const { return isSimple() ? V.isFloatingPoint() : isExtendedFloatingPoint(); } - /// isInteger - Return true if this is an integer, or a vector integer type. + /// Return true if this is an integer or a vector integer type. bool isInteger() const { return isSimple() ? V.isInteger() : isExtendedInteger(); } - /// isScalarInteger - Return true if this is an integer, but not a vector. + /// Return true if this is an integer, but not a vector. bool isScalarInteger() const { return isSimple() ? V.isScalarInteger() : isExtendedScalarInteger(); } - /// isVector - Return true if this is a vector value type. + /// Return true if this is a vector value type. bool isVector() const { return isSimple() ? V.isVector() : isExtendedVector(); } - /// is16BitVector - Return true if this is a 16-bit vector type. + /// Return true if this is a 16-bit vector type. bool is16BitVector() const { return isSimple() ? V.is16BitVector() : isExtended16BitVector(); } - /// is32BitVector - Return true if this is a 32-bit vector type. + /// Return true if this is a 32-bit vector type. bool is32BitVector() const { return isSimple() ? V.is32BitVector() : isExtended32BitVector(); } - /// is64BitVector - Return true if this is a 64-bit vector type. + /// Return true if this is a 64-bit vector type. bool is64BitVector() const { return isSimple() ? V.is64BitVector() : isExtended64BitVector(); } - /// is128BitVector - Return true if this is a 128-bit vector type. + /// Return true if this is a 128-bit vector type. bool is128BitVector() const { return isSimple() ? V.is128BitVector() : isExtended128BitVector(); } - /// is256BitVector - Return true if this is a 256-bit vector type. + /// Return true if this is a 256-bit vector type. bool is256BitVector() const { return isSimple() ? V.is256BitVector() : isExtended256BitVector(); } - /// is512BitVector - Return true if this is a 512-bit vector type. + /// Return true if this is a 512-bit vector type. bool is512BitVector() const { return isSimple() ? V.is512BitVector() : isExtended512BitVector(); } - /// is1024BitVector - Return true if this is a 1024-bit vector type. + /// Return true if this is a 1024-bit vector type. bool is1024BitVector() const { return isSimple() ? V.is1024BitVector() : isExtended1024BitVector(); } - /// is2048BitVector - Return true if this is a 2048-bit vector type. + /// Return true if this is a 2048-bit vector type. bool is2048BitVector() const { return isSimple() ? V.is2048BitVector() : isExtended2048BitVector(); } - /// isOverloaded - Return true if this is an overloaded type for TableGen. + /// Return true if this is an overloaded type for TableGen. bool isOverloaded() const { return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny); } - /// isByteSized - Return true if the bit size is a multiple of 8. + /// Return true if the bit size is a multiple of 8. bool isByteSized() const { return (getSizeInBits() & 7) == 0; } - /// isRound - Return true if the size is a power-of-two number of bytes. + /// Return true if the size is a power-of-two number of bytes. bool isRound() const { unsigned BitSize = getSizeInBits(); return BitSize >= 8 && !(BitSize & (BitSize - 1)); } - /// bitsEq - Return true if this has the same number of bits as VT. + /// Return true if this has the same number of bits as VT. bool bitsEq(EVT VT) const { if (EVT::operator==(VT)) return true; return getSizeInBits() == VT.getSizeInBits(); } - /// bitsGT - Return true if this has more bits than VT. + /// Return true if this has more bits than VT. bool bitsGT(EVT VT) const { if (EVT::operator==(VT)) return false; return getSizeInBits() > VT.getSizeInBits(); } - /// bitsGE - Return true if this has no less bits than VT. + /// Return true if this has no less bits than VT. bool bitsGE(EVT VT) const { if (EVT::operator==(VT)) return true; return getSizeInBits() >= VT.getSizeInBits(); } - /// bitsLT - Return true if this has less bits than VT. + /// Return true if this has less bits than VT. bool bitsLT(EVT VT) const { if (EVT::operator==(VT)) return false; return getSizeInBits() < VT.getSizeInBits(); } - /// bitsLE - Return true if this has no more bits than VT. + /// Return true if this has no more bits than VT. bool bitsLE(EVT VT) const { if (EVT::operator==(VT)) return true; return getSizeInBits() <= VT.getSizeInBits(); } - /// getSimpleVT - Return the SimpleValueType held in the specified - /// simple EVT. + /// Return the SimpleValueType held in the specified simple EVT. MVT getSimpleVT() const { assert(isSimple() && "Expected a SimpleValueType!"); return V; } - /// getScalarType - If this is a vector type, return the element type, - /// otherwise return this. + /// If this is a vector type, return the element type, otherwise return + /// this. EVT getScalarType() const { return isVector() ? getVectorElementType() : *this; } - /// getVectorElementType - Given a vector type, return the type of - /// each element. + /// Given a vector type, return the type of each element. EVT getVectorElementType() const { assert(isVector() && "Invalid vector type!"); if (isSimple()) @@ -243,8 +239,7 @@ namespace llvm { return getExtendedVectorElementType(); } - /// getVectorNumElements - Given a vector type, return the number of - /// elements it contains. + /// Given a vector type, return the number of elements it contains. unsigned getVectorNumElements() const { assert(isVector() && "Invalid vector type!"); if (isSimple()) @@ -252,7 +247,7 @@ namespace llvm { return getExtendedVectorNumElements(); } - /// getSizeInBits - Return the size of the specified value type in bits. + /// Return the size of the specified value type in bits. unsigned getSizeInBits() const { if (isSimple()) return V.getSizeInBits(); @@ -263,21 +258,21 @@ namespace llvm { return getScalarType().getSizeInBits(); } - /// getStoreSize - Return the number of bytes overwritten by a store - /// of the specified value type. + /// Return the number of bytes overwritten by a store of the specified value + /// type. unsigned getStoreSize() const { return (getSizeInBits() + 7) / 8; } - /// getStoreSizeInBits - Return the number of bits overwritten by a store - /// of the specified value type. + /// Return the number of bits overwritten by a store of the specified value + /// type. unsigned getStoreSizeInBits() const { return getStoreSize() * 8; } - /// getRoundIntegerType - Rounds the bit-width of the given integer EVT up - /// to the nearest power of two (and at least to eight), and returns the - /// integer EVT with that number of bits. + /// Rounds the bit-width of the given integer EVT up to the nearest power of + /// two (and at least to eight), and returns the integer EVT with that + /// number of bits. EVT getRoundIntegerType(LLVMContext &Context) const { assert(isInteger() && !isVector() && "Invalid integer type!"); unsigned BitWidth = getSizeInBits(); @@ -286,10 +281,9 @@ namespace llvm { return getIntegerVT(Context, 1 << Log2_32_Ceil(BitWidth)); } - /// getHalfSizedIntegerVT - Finds the smallest simple value type that is - /// greater than or equal to half the width of this EVT. If no simple - /// value type can be found, an extended integer value type of half the - /// size (rounded up) is returned. + /// Finds the smallest simple value type that is greater than or equal to + /// half the width of this EVT. If no simple value type can be found, an + /// extended integer value type of half the size (rounded up) is returned. EVT getHalfSizedIntegerVT(LLVMContext &Context) const { assert(isInteger() && !isVector() && "Invalid integer type!"); unsigned EVTSize = getSizeInBits(); @@ -302,7 +296,7 @@ namespace llvm { return getIntegerVT(Context, (EVTSize + 1) / 2); } - /// \brief Return a VT for an integer vector type with the size of the + /// Return a VT for an integer vector type with the size of the /// elements doubled. The typed returned may be an extended type. EVT widenIntegerVectorElementType(LLVMContext &Context) const { EVT EltVT = getVectorElementType(); @@ -310,14 +304,14 @@ namespace llvm { return EVT::getVectorVT(Context, EltVT, getVectorNumElements()); } - /// isPow2VectorType - Returns true if the given vector is a power of 2. + /// Returns true if the given vector is a power of 2. bool isPow2VectorType() const { unsigned NElts = getVectorNumElements(); return !(NElts & (NElts - 1)); } - /// getPow2VectorType - Widens the length of the given vector EVT up to - /// the nearest power of 2 and returns that type. + /// Widens the length of the given vector EVT up to the nearest power of 2 + /// and returns that type. EVT getPow2VectorType(LLVMContext &Context) const { if (!isPow2VectorType()) { unsigned NElts = getVectorNumElements(); @@ -329,16 +323,15 @@ namespace llvm { } } - /// getEVTString - This function returns value type as a string, - /// e.g. "i32". + /// This function returns value type as a string, e.g. "i32". std::string getEVTString() const; - /// getTypeForEVT - This method returns an LLVM type corresponding to the - /// specified EVT. For integer types, this returns an unsigned type. Note - /// that this will abort for types that cannot be represented. + /// This method returns an LLVM type corresponding to the specified EVT. + /// For integer types, this returns an unsigned type. Note that this will + /// abort for types that cannot be represented. Type *getTypeForEVT(LLVMContext &Context) const; - /// getEVT - Return the value type corresponding to the specified type. + /// Return the value type corresponding to the specified type. /// This returns all pointers as iPTR. If HandleUnknown is true, unknown /// types are returned as Other, otherwise they are invalid. static EVT getEVT(Type *Ty, bool HandleUnknown = false); @@ -350,8 +343,8 @@ namespace llvm { return (intptr_t)(LLVMTy); } - /// compareRawBits - A meaningless but well-behaved order, useful for - /// constructing containers. + /// A meaningless but well-behaved order, useful for constructing + /// containers. struct compareRawBits { bool operator()(EVT L, EVT R) const { if (L.V.SimpleTy == R.V.SimpleTy) |