aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /include/llvm/CodeGen
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Diffstat (limited to 'include/llvm/CodeGen')
-rw-r--r--include/llvm/CodeGen/Analysis.h7
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h91
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h175
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h10
-rw-r--r--include/llvm/CodeGen/CommandFlags.h33
-rw-r--r--include/llvm/CodeGen/ExecutionDepsFix.h220
-rw-r--r--include/llvm/CodeGen/FastISel.h87
-rw-r--r--include/llvm/CodeGen/FaultMaps.h43
-rw-r--r--include/llvm/CodeGen/GCStrategy.h46
-rw-r--r--include/llvm/CodeGen/GlobalISel/CallLowering.h51
-rw-r--r--include/llvm/CodeGen/GlobalISel/IRTranslator.h96
-rw-r--r--include/llvm/CodeGen/GlobalISel/InstructionSelector.h13
-rw-r--r--include/llvm/CodeGen/GlobalISel/Legalizer.h3
-rw-r--r--include/llvm/CodeGen/GlobalISel/LegalizerHelper.h12
-rw-r--r--include/llvm/CodeGen/GlobalISel/LegalizerInfo.h8
-rw-r--r--include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h150
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegBankSelect.h4
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBank.h2
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h20
-rw-r--r--include/llvm/CodeGen/GlobalISel/Utils.h21
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h25
-rw-r--r--include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h76
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h38
-rw-r--r--include/llvm/CodeGen/LiveInterval.h28
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h140
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h117
-rw-r--r--include/llvm/CodeGen/LiveRegMatrix.h21
-rw-r--r--include/llvm/CodeGen/LiveRegUnits.h128
-rw-r--r--include/llvm/CodeGen/LowLevelType.h190
-rw-r--r--include/llvm/CodeGen/MIRYamlMapping.h4
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h23
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h8
-rw-r--r--include/llvm/CodeGen/MachineDominators.h22
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h10
-rw-r--r--include/llvm/CodeGen/MachineFunction.h5
-rw-r--r--include/llvm/CodeGen/MachineFunctionInitializer.h2
-rw-r--r--include/llvm/CodeGen/MachineInstr.h29
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h35
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h7
-rw-r--r--include/llvm/CodeGen/MachineModuleInfoImpls.h29
-rw-r--r--include/llvm/CodeGen/MachineOperand.h30
-rw-r--r--include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h203
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h92
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h100
-rw-r--r--include/llvm/CodeGen/MachineTraceMetrics.h66
-rw-r--r--include/llvm/CodeGen/MachineValueType.h81
-rw-r--r--include/llvm/CodeGen/PBQP/Solution.h21
-rw-r--r--include/llvm/CodeGen/Passes.h28
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h82
-rw-r--r--include/llvm/CodeGen/RegisterClassInfo.h43
-rw-r--r--include/llvm/CodeGen/RegisterPressure.h72
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h42
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h509
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h139
-rw-r--r--include/llvm/CodeGen/ScheduleDAGMutation.h25
-rw-r--r--include/llvm/CodeGen/ScheduleDFS.h26
-rw-r--r--include/llvm/CodeGen/ScheduleHazardRecognizer.h8
-rw-r--r--include/llvm/CodeGen/ScoreboardHazardRecognizer.h22
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h44
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h23
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h162
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h22
-rw-r--r--include/llvm/CodeGen/StackMaps.h51
-rw-r--r--include/llvm/CodeGen/StackProtector.h18
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h60
-rw-r--r--include/llvm/CodeGen/TargetPassConfig.h13
-rw-r--r--include/llvm/CodeGen/TargetSchedule.h28
-rw-r--r--include/llvm/CodeGen/ValueTypes.h131
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)