summaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /include/llvm/CodeGen
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
Diffstat (limited to 'include/llvm/CodeGen')
-rw-r--r--include/llvm/CodeGen/Analysis.h2
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h11
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h215
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h20
-rw-r--r--include/llvm/CodeGen/CommandFlags.h64
-rw-r--r--include/llvm/CodeGen/DFAPacketizer.h94
-rw-r--r--include/llvm/CodeGen/DIE.h69
-rw-r--r--include/llvm/CodeGen/DIEValue.def1
-rw-r--r--include/llvm/CodeGen/FastISel.h10
-rw-r--r--include/llvm/CodeGen/FaultMaps.h1
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h72
-rw-r--r--include/llvm/CodeGen/GCMetadata.h5
-rw-r--r--include/llvm/CodeGen/GlobalISel/CallLowering.h72
-rw-r--r--include/llvm/CodeGen/GlobalISel/GISelAccessor.h33
-rw-r--r--include/llvm/CodeGen/GlobalISel/IRTranslator.h158
-rw-r--r--include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h146
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegBankSelect.h614
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBank.h101
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h602
-rw-r--r--include/llvm/CodeGen/GlobalISel/Types.h32
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h55
-rw-r--r--include/llvm/CodeGen/LiveInterval.h18
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h28
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h36
-rw-r--r--include/llvm/CodeGen/LiveRangeEdit.h45
-rw-r--r--include/llvm/CodeGen/LiveVariables.h49
-rw-r--r--include/llvm/CodeGen/MIRParser/MIRParser.h2
-rw-r--r--include/llvm/CodeGen/MIRYamlMapping.h6
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h95
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineCombinerPattern.h35
-rw-r--r--include/llvm/CodeGen/MachineDominators.h23
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h130
-rw-r--r--include/llvm/CodeGen/MachineFunction.h102
-rw-r--r--include/llvm/CodeGen/MachineFunctionPass.h26
-rw-r--r--include/llvm/CodeGen/MachineInstr.h61
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h158
-rw-r--r--include/llvm/CodeGen/MachineInstrBundle.h43
-rw-r--r--include/llvm/CodeGen/MachineInstrBundleIterator.h92
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h54
-rw-r--r--include/llvm/CodeGen/MachineMemOperand.h136
-rw-r--r--include/llvm/CodeGen/MachineModuleInfoImpls.h27
-rw-r--r--include/llvm/CodeGen/MachineOperand.h9
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h149
-rw-r--r--include/llvm/CodeGen/MachineSSAUpdater.h1
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h96
-rw-r--r--include/llvm/CodeGen/MachineTraceMetrics.h13
-rw-r--r--include/llvm/CodeGen/MachineValueType.h25
-rw-r--r--include/llvm/CodeGen/PBQP/Graph.h16
-rw-r--r--include/llvm/CodeGen/ParallelCG.h25
-rw-r--r--include/llvm/CodeGen/Passes.h421
-rw-r--r--include/llvm/CodeGen/PreISelIntrinsicLowering.h26
-rw-r--r--include/llvm/CodeGen/PseudoSourceValue.h4
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h1
-rw-r--r--include/llvm/CodeGen/RegisterPressure.h128
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h13
-rw-r--r--include/llvm/CodeGen/RegisterUsageInfo.h75
-rw-r--r--include/llvm/CodeGen/ResourcePriorityQueue.h8
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h86
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h11
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h76
-rw-r--r--include/llvm/CodeGen/ScheduleDAGMutation.h31
-rw-r--r--include/llvm/CodeGen/ScheduleHazardRecognizer.h11
-rw-r--r--include/llvm/CodeGen/ScoreboardHazardRecognizer.h6
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h544
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h42
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h507
-rw-r--r--include/llvm/CodeGen/SelectionDAGTargetInfo.h156
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h78
-rw-r--r--include/llvm/CodeGen/StackMaps.h2
-rw-r--r--include/llvm/CodeGen/StackProtector.h10
-rw-r--r--include/llvm/CodeGen/TailDuplicator.h92
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h19
-rw-r--r--include/llvm/CodeGen/TargetPassConfig.h376
-rw-r--r--include/llvm/CodeGen/UnreachableBlockElim.h37
-rw-r--r--include/llvm/CodeGen/ValueTypes.h8
-rw-r--r--include/llvm/CodeGen/ValueTypes.td20
-rw-r--r--include/llvm/CodeGen/WinEHFuncInfo.h2
78 files changed, 4836 insertions, 1835 deletions
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h
index 38e64ad3be29a..2e4dc49a1e26b 100644
--- a/include/llvm/CodeGen/Analysis.h
+++ b/include/llvm/CodeGen/Analysis.h
@@ -17,10 +17,12 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/Support/CodeGen.h"
namespace llvm {
class GlobalValue;
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index cf29fc9ef889f..de618d1735733 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -34,6 +34,7 @@ class ConstantArray;
class DIE;
class DIEAbbrev;
class GCMetadataPrinter;
+class GlobalIndirectSymbol;
class GlobalValue;
class GlobalVariable;
class MachineBasicBlock;
@@ -147,6 +148,8 @@ public:
DwarfDebug *getDwarfDebug() { return DD; }
DwarfDebug *getDwarfDebug() const { return DD; }
+ bool isPositionIndependent() const;
+
/// Return true if assembly output should contain comments.
///
bool isVerbose() const { return VerboseAsm; }
@@ -238,11 +241,6 @@ public:
///
virtual void EmitJumpTableInfo();
- /// Emit the control variable for an emulated TLS variable.
- virtual void EmitEmulatedTLSControlVariable(const GlobalVariable *GV,
- MCSymbol *EmittedSym,
- bool AllZeroInitValue);
-
/// Emit the specified global variable to the .s file.
virtual void EmitGlobalVariable(const GlobalVariable *GV);
@@ -551,6 +549,9 @@ private:
void EmitXXStructorList(const DataLayout &DL, const Constant *List,
bool isCtor);
GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C);
+ /// Emit GlobalAlias or GlobalIFunc.
+ void emitGlobalIndirectSymbol(Module &M,
+ const GlobalIndirectSymbol& GIS);
};
}
diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h
index d99054eb6f368..69951afb623c3 100644
--- a/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/include/llvm/CodeGen/BasicTTIImpl.h
@@ -105,6 +105,11 @@ public:
/// \name Scalar TTI Implementations
/// @{
+ bool allowsMisalignedMemoryAccesses(unsigned BitWidth, unsigned AddressSpace,
+ unsigned Alignment, bool *Fast) const {
+ MVT M = MVT::getIntegerVT(BitWidth);
+ return getTLI()->allowsMisalignedMemoryAccesses(M, AddressSpace, Alignment, Fast);
+ }
bool hasBranchDivergence() { return false; }
@@ -152,6 +157,11 @@ public:
return getTLI()->isTypeLegal(VT);
}
+ int getGEPCost(Type *PointeeType, const Value *Ptr,
+ ArrayRef<const Value *> Operands) {
+ return BaseT::getGEPCost(PointeeType, Ptr, Operands);
+ }
+
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) {
return BaseT::getIntrinsicCost(IID, RetTy, Arguments);
@@ -216,6 +226,8 @@ public:
return BaseT::getOperationCost(Opcode, Ty, OpTy);
}
+ unsigned getInliningThresholdMultiplier() { return 1; }
+
void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) {
// This unrolling functionality is target independent, but to provide some
// motivation for its intended use, for x86:
@@ -307,12 +319,14 @@ public:
}
if (!TLI->isOperationExpand(ISD, LT.second)) {
- // If the operation is custom lowered then assume
- // thare the code is twice as expensive.
+ // If the operation is custom lowered, then assume that the code is twice
+ // as expensive.
return LT.first * 2 * OpCost;
}
// Else, assume that we need to scalarize this op.
+ // TODO: If one of the types get legalized by splitting, handle this
+ // similarly to what getCastInstrCost() does.
if (Ty->isVectorTy()) {
unsigned Num = Ty->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)
@@ -359,6 +373,11 @@ public:
TLI->isZExtFree(SrcLT.second, DstLT.second))
return 0;
+ if (Opcode == Instruction::AddrSpaceCast &&
+ TLI->isNoopAddrSpaceCast(Src->getPointerAddressSpace(),
+ Dst->getPointerAddressSpace()))
+ 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))
@@ -402,9 +421,25 @@ public:
return SrcLT.first * 1;
}
- // If we are converting vectors and the operation is illegal, or
- // if the vectors are legalized to different types, estimate the
- // scalarization costs.
+ // If we are legalizing by splitting, query the concrete TTI for the cost
+ // of casting the original vector twice. We also need to factor int the
+ // cost of the split itself. Count that as 1, to be consistent with
+ // TLI->getTypeLegalizationCost().
+ if ((TLI->getTypeAction(Src->getContext(), TLI->getValueType(DL, Src)) ==
+ TargetLowering::TypeSplitVector) ||
+ (TLI->getTypeAction(Dst->getContext(), TLI->getValueType(DL, Dst)) ==
+ TargetLowering::TypeSplitVector)) {
+ Type *SplitDst = VectorType::get(Dst->getVectorElementType(),
+ Dst->getVectorNumElements() / 2);
+ Type *SplitSrc = VectorType::get(Src->getVectorElementType(),
+ Src->getVectorNumElements() / 2);
+ T *TTI = static_cast<T *>(this);
+ return TTI->getVectorSplitCost() +
+ (2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc));
+ }
+
+ // 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());
@@ -428,6 +463,14 @@ public:
llvm_unreachable("Unhandled cast");
}
+ unsigned getExtractWithExtendCost(unsigned Opcode, Type *Dst,
+ VectorType *VecTy, unsigned Index) {
+ return static_cast<T *>(this)->getVectorInstrCost(
+ Instruction::ExtractElement, VecTy, Index) +
+ static_cast<T *>(this)->getCastInstrCost(Opcode, Dst,
+ VecTy->getElementType());
+ }
+
unsigned getCFInstrCost(unsigned Opcode) {
// Branches are assumed to be predicted.
return 0;
@@ -454,6 +497,8 @@ public:
}
// Otherwise, assume that the cast is scalarized.
+ // TODO: If one of the types get legalized by splitting, handle this
+ // similarly to what getCastInstrCost() does.
if (ValTy->isVectorTy()) {
unsigned Num = ValTy->getVectorNumElements();
if (CondTy)
@@ -462,8 +507,7 @@ public:
Opcode, ValTy->getScalarType(), CondTy);
// Return the cost of multiple scalar invocation plus the cost of
- // inserting
- // and extracting the values.
+ // inserting and extracting the values.
return getScalarizationOverhead(ValTy, true, false) + Num * Cost;
}
@@ -527,6 +571,51 @@ public:
unsigned Cost = static_cast<T *>(this)->getMemoryOpCost(
Opcode, VecTy, Alignment, AddressSpace);
+ // Legalize the vector type, and get the legalized and unlegalized type
+ // sizes.
+ MVT VecTyLT = getTLI()->getTypeLegalizationCost(DL, VecTy).second;
+ unsigned VecTySize =
+ static_cast<T *>(this)->getDataLayout().getTypeStoreSize(VecTy);
+ unsigned VecTyLTSize = VecTyLT.getStoreSize();
+
+ // Return the ceiling of dividing A by B.
+ auto ceil = [](unsigned A, unsigned B) { return (A + B - 1) / B; };
+
+ // Scale the cost of the memory operation by the fraction of legalized
+ // instructions that will actually be used. We shouldn't account for the
+ // cost of dead instructions since they will be removed.
+ //
+ // E.g., An interleaved load of factor 8:
+ // %vec = load <16 x i64>, <16 x i64>* %ptr
+ // %v0 = shufflevector %vec, undef, <0, 8>
+ //
+ // If <16 x i64> is legalized to 8 v2i64 loads, only 2 of the loads will be
+ // used (those corresponding to elements [0:1] and [8:9] of the unlegalized
+ // type). The other loads are unused.
+ //
+ // We only scale the cost of loads since interleaved store groups aren't
+ // allowed to have gaps.
+ if (Opcode == Instruction::Load && VecTySize > VecTyLTSize) {
+
+ // The number of loads of a legal type it will take to represent a load
+ // of the unlegalized vector type.
+ unsigned NumLegalInsts = ceil(VecTySize, VecTyLTSize);
+
+ // The number of elements of the unlegalized type that correspond to a
+ // single legal instruction.
+ unsigned NumEltsPerLegalInst = ceil(NumElts, NumLegalInsts);
+
+ // Determine which legal instructions will be used.
+ BitVector UsedInsts(NumLegalInsts, false);
+ for (unsigned Index : Indices)
+ for (unsigned Elt = 0; Elt < NumSubElts; ++Elt)
+ UsedInsts.set((Index + Elt * Factor) / NumEltsPerLegalInst);
+
+ // Scale the cost of the load by the fraction of legal instructions that
+ // will be used.
+ Cost *= UsedInsts.count() / NumLegalInsts;
+ }
+
// Then plus the cost of interleave operation.
if (Opcode == Instruction::Load) {
// The interleave cost is similar to extract sub vectors' elements
@@ -582,13 +671,14 @@ public:
/// Get intrinsic cost based on arguments
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Value *> Args) {
+ ArrayRef<Value *> Args, FastMathFlags FMF) {
switch (IID) {
default: {
SmallVector<Type *, 4> Types;
for (Value *Op : Args)
Types.push_back(Op->getType());
- return getIntrinsicInstrCost(IID, RetTy, Types);
+ return static_cast<T *>(this)->getIntrinsicInstrCost(IID, RetTy, Types,
+ FMF);
}
case Intrinsic::masked_scatter: {
Value *Mask = Args[3];
@@ -614,8 +704,9 @@ public:
/// Get intrinsic cost based on argument types
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Type *> Tys) {
- unsigned ISD = 0;
+ ArrayRef<Type *> Tys, FastMathFlags FMF) {
+ SmallVector<unsigned, 2> ISDs;
+ unsigned SingleCallCost = 10; // Library call cost. Make it expensive.
switch (IID) {
default: {
// Assume that we need to scalarize this intrinsic.
@@ -641,74 +732,78 @@ public:
return 1; // Return cost of a scalar intrinsic. Assume it to be cheap.
unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
- IID, ScalarRetTy, ScalarTys);
+ IID, ScalarRetTy, ScalarTys, FMF);
return ScalarCalls * ScalarCost + ScalarizationCost;
}
// Look for intrinsics that can be lowered directly or turned into a scalar
// intrinsic call.
case Intrinsic::sqrt:
- ISD = ISD::FSQRT;
+ ISDs.push_back(ISD::FSQRT);
break;
case Intrinsic::sin:
- ISD = ISD::FSIN;
+ ISDs.push_back(ISD::FSIN);
break;
case Intrinsic::cos:
- ISD = ISD::FCOS;
+ ISDs.push_back(ISD::FCOS);
break;
case Intrinsic::exp:
- ISD = ISD::FEXP;
+ ISDs.push_back(ISD::FEXP);
break;
case Intrinsic::exp2:
- ISD = ISD::FEXP2;
+ ISDs.push_back(ISD::FEXP2);
break;
case Intrinsic::log:
- ISD = ISD::FLOG;
+ ISDs.push_back(ISD::FLOG);
break;
case Intrinsic::log10:
- ISD = ISD::FLOG10;
+ ISDs.push_back(ISD::FLOG10);
break;
case Intrinsic::log2:
- ISD = ISD::FLOG2;
+ ISDs.push_back(ISD::FLOG2);
break;
case Intrinsic::fabs:
- ISD = ISD::FABS;
+ ISDs.push_back(ISD::FABS);
break;
case Intrinsic::minnum:
- ISD = ISD::FMINNUM;
+ ISDs.push_back(ISD::FMINNUM);
+ if (FMF.noNaNs())
+ ISDs.push_back(ISD::FMINNAN);
break;
case Intrinsic::maxnum:
- ISD = ISD::FMAXNUM;
+ ISDs.push_back(ISD::FMAXNUM);
+ if (FMF.noNaNs())
+ ISDs.push_back(ISD::FMAXNAN);
break;
case Intrinsic::copysign:
- ISD = ISD::FCOPYSIGN;
+ ISDs.push_back(ISD::FCOPYSIGN);
break;
case Intrinsic::floor:
- ISD = ISD::FFLOOR;
+ ISDs.push_back(ISD::FFLOOR);
break;
case Intrinsic::ceil:
- ISD = ISD::FCEIL;
+ ISDs.push_back(ISD::FCEIL);
break;
case Intrinsic::trunc:
- ISD = ISD::FTRUNC;
+ ISDs.push_back(ISD::FTRUNC);
break;
case Intrinsic::nearbyint:
- ISD = ISD::FNEARBYINT;
+ ISDs.push_back(ISD::FNEARBYINT);
break;
case Intrinsic::rint:
- ISD = ISD::FRINT;
+ ISDs.push_back(ISD::FRINT);
break;
case Intrinsic::round:
- ISD = ISD::FROUND;
+ ISDs.push_back(ISD::FROUND);
break;
case Intrinsic::pow:
- ISD = ISD::FPOW;
+ ISDs.push_back(ISD::FPOW);
break;
case Intrinsic::fma:
- ISD = ISD::FMA;
+ ISDs.push_back(ISD::FMA);
break;
case Intrinsic::fmuladd:
- ISD = ISD::FMA;
+ ISDs.push_back(ISD::FMA);
break;
// FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free.
case Intrinsic::lifetime_start:
@@ -720,27 +815,49 @@ public:
case Intrinsic::masked_load:
return static_cast<T *>(this)
->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
+ case Intrinsic::ctpop:
+ ISDs.push_back(ISD::CTPOP);
+ // In case of legalization use TCC_Expensive. This is cheaper than a
+ // library call but still not a cheap instruction.
+ SingleCallCost = TargetTransformInfo::TCC_Expensive;
+ break;
+ // FIXME: ctlz, cttz, ...
}
const TargetLoweringBase *TLI = getTLI();
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, RetTy);
- if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
- // The operation is legal. Assume it costs 1.
- // If the type is split to multiple registers, assume that there is some
- // overhead to this.
- // TODO: Once we have extract/insert subvector cost we need to use them.
- if (LT.first > 1)
- return LT.first * 2;
- return LT.first * 1;
- }
+ SmallVector<unsigned, 2> LegalCost;
+ SmallVector<unsigned, 2> CustomCost;
+ for (unsigned ISD : ISDs) {
+ if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
+ if (IID == Intrinsic::fabs && TLI->isFAbsFree(LT.second)) {
+ return 0;
+ }
- if (!TLI->isOperationExpand(ISD, LT.second)) {
- // If the operation is custom lowered then assume
- // thare the code is twice as expensive.
- return LT.first * 2;
+ // The operation is legal. Assume it costs 1.
+ // If the type is split to multiple registers, assume that there is some
+ // overhead to this.
+ // TODO: Once we have extract/insert subvector cost we need to use them.
+ if (LT.first > 1)
+ LegalCost.push_back(LT.first * 2);
+ else
+ LegalCost.push_back(LT.first * 1);
+ } else if (!TLI->isOperationExpand(ISD, LT.second)) {
+ // If the operation is custom lowered then assume
+ // that the code is twice as expensive.
+ CustomCost.push_back(LT.first * 2);
+ }
}
+ auto MinLegalCostI = std::min_element(LegalCost.begin(), LegalCost.end());
+ if (MinLegalCostI != LegalCost.end())
+ return *MinLegalCostI;
+
+ auto MinCustomCostI = std::min_element(CustomCost.begin(), CustomCost.end());
+ if (MinCustomCostI != CustomCost.end())
+ return *MinCustomCostI;
+
// If we can't lower fmuladd into an FMA estimate the cost as a floating
// point mul followed by an add.
if (IID == Intrinsic::fmuladd)
@@ -763,7 +880,7 @@ public:
ScalarTys.push_back(Ty);
}
unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
- IID, RetTy->getScalarType(), ScalarTys);
+ 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);
@@ -775,7 +892,7 @@ public:
}
// This is going to be turned into a library call, make it expensive.
- return 10;
+ return SingleCallCost;
}
/// \brief Compute a cost of the given call instruction.
@@ -815,6 +932,8 @@ public:
return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true);
}
+ unsigned getVectorSplitCost() { return 1; }
+
/// @}
};
diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h
index 415abb90da576..92e58564e0408 100644
--- a/include/llvm/CodeGen/CallingConvLower.h
+++ b/include/llvm/CodeGen/CallingConvLower.h
@@ -195,6 +195,7 @@ class CCState {
private:
CallingConv::ID CallingConv;
bool IsVarArg;
+ bool AnalyzingMustTailForwardedRegs = false;
MachineFunction &MF;
const TargetRegisterInfo &TRI;
SmallVectorImpl<CCValAssign> &Locs;
@@ -281,7 +282,7 @@ public:
/// be able to store all arguments and such that the alignment requirement
/// of each of the arguments is satisfied.
unsigned getAlignedCallFrameSize() const {
- return RoundUpToAlignment(StackOffset, MaxStackArgAlign);
+ return alignTo(StackOffset, MaxStackArgAlign);
}
/// isAllocated - Return true if the specified register (or an alias) is
@@ -412,14 +413,19 @@ public:
/// and alignment.
unsigned AllocateStack(unsigned Size, unsigned Align) {
assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2.
- StackOffset = RoundUpToAlignment(StackOffset, Align);
+ StackOffset = alignTo(StackOffset, Align);
unsigned Result = StackOffset;
StackOffset += Size;
MaxStackArgAlign = std::max(Align, MaxStackArgAlign);
- MF.getFrameInfo()->ensureMaxAlignment(Align);
+ ensureMaxAlignment(Align);
return Result;
}
+ void ensureMaxAlignment(unsigned Align) {
+ if (!AnalyzingMustTailForwardedRegs)
+ MF.getFrameInfo()->ensureMaxAlignment(Align);
+ }
+
/// Version of AllocateStack with extra register to be shadowed.
unsigned AllocateStack(unsigned Size, unsigned Align, unsigned ShadowReg) {
MarkAllocated(ShadowReg);
@@ -507,6 +513,14 @@ public:
SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,
CCAssignFn Fn);
+ /// Returns true if the results of the two calling conventions are compatible.
+ /// This is usually part of the check for tailcall eligibility.
+ static bool resultsCompatible(CallingConv::ID CalleeCC,
+ CallingConv::ID CallerCC, MachineFunction &MF,
+ LLVMContext &C,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ CCAssignFn CalleeFn, CCAssignFn CallerFn);
+
private:
/// MarkAllocated - Mark a register and all of its aliases as allocated.
void MarkAllocated(unsigned Reg);
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
index 0d37dc00422fa..6376c06768b3a 100644
--- a/include/llvm/CodeGen/CommandFlags.h
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -46,20 +46,23 @@ MAttrs("mattr",
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
-cl::opt<Reloc::Model>
-RelocModel("relocation-model",
- cl::desc("Choose relocation model"),
- cl::init(Reloc::Default),
- cl::values(
- clEnumValN(Reloc::Default, "default",
- "Target default relocation model"),
- clEnumValN(Reloc::Static, "static",
- "Non-relocatable code"),
- clEnumValN(Reloc::PIC_, "pic",
- "Fully relocatable, position independent code"),
- clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
- "Relocatable external references, non-relocatable code"),
- clEnumValEnd));
+cl::opt<Reloc::Model> RelocModel(
+ "relocation-model", cl::desc("Choose relocation model"),
+ cl::values(
+ clEnumValN(Reloc::Static, "static", "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static inline Optional<Reloc::Model> getRelocModel() {
+ if (RelocModel.getNumOccurrences()) {
+ Reloc::Model R = RelocModel;
+ return R;
+ }
+ return None;
+}
cl::opt<ThreadModel::Model>
TMModel("thread-model",
@@ -87,6 +90,22 @@ CMModel("code-model",
"Large code model"),
clEnumValEnd));
+cl::opt<llvm::ExceptionHandling>
+ExceptionModel("exception-model",
+ cl::desc("exception model"),
+ cl::init(ExceptionHandling::None),
+ cl::values(clEnumValN(ExceptionHandling::None, "default",
+ "default exception handling model"),
+ clEnumValN(ExceptionHandling::DwarfCFI, "dwarf",
+ "DWARF-like CFI based exception handling"),
+ clEnumValN(ExceptionHandling::SjLj, "sjlj",
+ "SjLj exception handling"),
+ clEnumValN(ExceptionHandling::ARM, "arm",
+ "ARM EHABI exceptions"),
+ clEnumValN(ExceptionHandling::WinEH, "wineh",
+ "Windows exception model"),
+ clEnumValEnd));
+
cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
cl::desc("Choose a file type (not all types are supported by all targets):"),
@@ -177,6 +196,11 @@ DisableTailCalls("disable-tail-calls",
cl::desc("Never emit tail calls"),
cl::init(false));
+cl::opt<bool>
+StackSymbolOrdering("stack-symbol-ordering",
+ cl::desc("Order local stack symbols."),
+ cl::init(true));
+
cl::opt<unsigned>
OverrideStackAlignment("stack-alignment",
cl::desc("Override default stack alignment"),
@@ -193,11 +217,6 @@ TrapFuncName("trap-func", cl::Hidden,
cl::init(""));
cl::opt<bool>
-EnablePIE("enable-pie",
- cl::desc("Assume the creation of a position independent executable."),
- cl::init(false));
-
-cl::opt<bool>
UseCtors("use-ctors",
cl::desc("Use .ctors instead of .init_array."),
cl::init(false));
@@ -211,10 +230,6 @@ cl::opt<std::string> StartAfter("start-after",
cl::value_desc("pass-name"),
cl::init(""));
-cl::opt<std::string>
- RunPass("run-pass", cl::desc("Run compiler only for one specific pass"),
- cl::value_desc("pass-name"), cl::init(""));
-
cl::opt<bool> DataSections("data-sections",
cl::desc("Emit data into separate sections"),
cl::init(false));
@@ -284,12 +299,13 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.NoZerosInBSS = DontPlaceZerosInBSS;
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.PositionIndependentExecutable = EnablePIE;
+ Options.StackSymbolOrdering = StackSymbolOrdering;
Options.UseInitArray = !UseCtors;
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
Options.UniqueSectionNames = UniqueSectionNames;
Options.EmulatedTLS = EmulatedTLS;
+ Options.ExceptionModel = ExceptionModel;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h
index 40ec201107e8e..8de140e91bf37 100644
--- a/include/llvm/CodeGen/DFAPacketizer.h
+++ b/include/llvm/CodeGen/DFAPacketizer.h
@@ -28,6 +28,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include <map>
namespace llvm {
@@ -80,7 +81,7 @@ private:
// CachedTable is a map from <FromState, Input> to ToState.
DenseMap<UnsignPair, unsigned> CachedTable;
- // ReadTable - Read the DFA transition table and update CachedTable.
+ // Read the DFA transition table and update CachedTable.
void ReadTable(unsigned state);
public:
@@ -92,38 +93,39 @@ public:
CurrentState = 0;
}
- // getInsnInput - Return the DFAInput for an instruction class.
+ // Return the DFAInput for an instruction class.
DFAInput getInsnInput(unsigned InsnClass);
- // getInsnInput - Return the DFAInput for an instruction class input vector.
+ // Return the DFAInput for an instruction class input vector.
static DFAInput getInsnInput(const std::vector<unsigned> &InsnClass);
- // canReserveResources - Check if the resources occupied by a MCInstrDesc
- // are available in the current state.
+ // Check if the resources occupied by a MCInstrDesc are available in
+ // the current state.
bool canReserveResources(const llvm::MCInstrDesc *MID);
- // reserveResources - Reserve the resources occupied by a MCInstrDesc and
- // change the current state to reflect that change.
+ // Reserve the resources occupied by a MCInstrDesc and change the current
+ // state to reflect that change.
void reserveResources(const llvm::MCInstrDesc *MID);
- // canReserveResources - Check if the resources occupied by a machine
- // instruction are available in the current state.
- bool canReserveResources(llvm::MachineInstr *MI);
+ // Check if the resources occupied by a machine instruction are available
+ // in the current state.
+ bool canReserveResources(llvm::MachineInstr &MI);
- // reserveResources - Reserve the resources occupied by a machine
- // instruction and change the current state to reflect that change.
- void reserveResources(llvm::MachineInstr *MI);
+ // Reserve the resources occupied by a machine instruction and change the
+ // current state to reflect that change.
+ void reserveResources(llvm::MachineInstr &MI);
const InstrItineraryData *getInstrItins() const { return InstrItins; }
};
-// VLIWPacketizerList - Implements a simple VLIW packetizer using DFA. The
-// packetizer works on machine basic blocks. For each instruction I in BB, the
-// packetizer consults the DFA to see if machine resources are available to
-// execute I. If so, the packetizer checks if I depends on any instruction J in
-// the current packet. If no dependency is found, I is added to current packet
-// and machine resource is marked as taken. If any dependency is found, a target
-// API call is made to prune the dependence.
+
+// VLIWPacketizerList implements a simple VLIW packetizer using DFA. The
+// packetizer works on machine basic blocks. For each instruction I in BB,
+// the packetizer consults the DFA to see if machine resources are available
+// to execute I. If so, the packetizer checks if I depends on any instruction
+// in the current packet. If no dependency is found, I is added to current
+// packet and the machine resource is marked as taken. If any dependency is
+// found, a target API call is made to prune the dependence.
class VLIWPacketizerList {
protected:
MachineFunction &MF;
@@ -132,13 +134,11 @@ protected:
// The VLIW Scheduler.
DefaultVLIWScheduler *VLIWScheduler;
-
// Vector of instructions assigned to the current packet.
std::vector<MachineInstr*> CurrentPacketMIs;
// DFA resource tracker.
DFAPacketizer *ResourceTracker;
-
- // Generate MI -> SU map.
+ // Map: MI -> SU.
std::map<MachineInstr*, SUnit*> MIToSUnit;
public:
@@ -148,43 +148,40 @@ public:
virtual ~VLIWPacketizerList();
- // PacketizeMIs - Implement this API in the backend to bundle instructions.
+ // Implement this API in the backend to bundle instructions.
void PacketizeMIs(MachineBasicBlock *MBB,
MachineBasicBlock::iterator BeginItr,
MachineBasicBlock::iterator EndItr);
- // getResourceTracker - return ResourceTracker
+ // Return the ResourceTracker.
DFAPacketizer *getResourceTracker() {return ResourceTracker;}
// addToPacket - Add MI to the current packet.
- virtual MachineBasicBlock::iterator addToPacket(MachineInstr *MI) {
- MachineBasicBlock::iterator MII = MI;
- CurrentPacketMIs.push_back(MI);
+ virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI) {
+ CurrentPacketMIs.push_back(&MI);
ResourceTracker->reserveResources(MI);
- return MII;
+ return MI;
}
// End the current packet and reset the state of the packetizer.
// Overriding this function allows the target-specific packetizer
// to perform custom finalization.
- virtual void endPacket(MachineBasicBlock *MBB, MachineInstr *MI);
+ virtual void endPacket(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator MI);
- // initPacketizerState - perform initialization before packetizing
- // an instruction. This function is supposed to be overrided by
- // the target dependent packetizer.
- virtual void initPacketizerState() { return; }
+ // Perform initialization before packetizing an instruction. This
+ // function is supposed to be overrided by the target dependent packetizer.
+ virtual void initPacketizerState() {}
- // ignorePseudoInstruction - Ignore bundling of pseudo instructions.
- virtual bool ignorePseudoInstruction(const MachineInstr *I,
+ // Check if the given instruction I should be ignored by the packetizer.
+ virtual bool ignorePseudoInstruction(const MachineInstr &I,
const MachineBasicBlock *MBB) {
return false;
}
- // isSoloInstruction - return true if instruction MI can not be packetized
- // with any other instruction, which means that MI itself is a packet.
- virtual bool isSoloInstruction(const MachineInstr *MI) {
- return true;
- }
+ // Return true if instruction MI can not be packetized with any other
+ // instruction, which means that MI itself is a packet.
+ virtual bool isSoloInstruction(const MachineInstr &MI) { return true; }
// Check if the packetizer should try to add the given instruction to
// the current packet. One reasons for which it may not be desirable
@@ -192,23 +189,22 @@ public:
// would cause a stall.
// If this function returns "false", the current packet will be ended,
// and the instruction will be added to the next packet.
- virtual bool shouldAddToPacket(const MachineInstr *MI) {
- return true;
- }
+ virtual bool shouldAddToPacket(const MachineInstr &MI) { return true; }
- // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ
- // together.
+ // Check if it is legal to packetize SUI and SUJ together.
virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
return false;
}
- // isLegalToPruneDependencies - Is it legal to prune dependece between SUI
- // and SUJ.
+ // Check if it is legal to prune dependece between SUI and SUJ.
virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {
return false;
}
+ // Add a DAG mutation to be done before the packetization begins.
+ void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation);
};
-}
+
+} // namespace llvm
#endif
diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h
index 72b3adc7de99b..7d6e66fa6ec2a 100644
--- a/include/llvm/CodeGen/DIE.h
+++ b/include/llvm/CodeGen/DIE.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/Support/Dwarf.h"
-#include <vector>
namespace llvm {
class AsmPrinter;
@@ -29,48 +28,6 @@ class MCSymbol;
class raw_ostream;
class DwarfTypeUnit;
-// AsmStreamerBase - A base abstract interface class defines methods that
-// can be implemented to stream objects or can be implemented to
-// calculate the size of the streamed objects.
-// The derived classes will use an AsmPrinter to implement the methods.
-//
-// TODO: complete this interface and use it to merge EmitValue and SizeOf
-// methods in the DIE classes below.
-class AsmStreamerBase {
-protected:
- const AsmPrinter *AP;
- AsmStreamerBase(const AsmPrinter *AP) : AP(AP) {}
-
-public:
- virtual ~AsmStreamerBase() {}
- virtual unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
- unsigned PadTo = 0) = 0;
- virtual unsigned emitInt8(unsigned char Value) = 0;
- virtual unsigned emitBytes(StringRef Data) = 0;
-};
-
-/// EmittingAsmStreamer - Implements AbstractAsmStreamer to stream objects.
-/// Notice that the return value is not the actual size of the streamed object.
-/// For size calculation use SizeReporterAsmStreamer.
-class EmittingAsmStreamer : public AsmStreamerBase {
-public:
- EmittingAsmStreamer(const AsmPrinter *AP) : AsmStreamerBase(AP) {}
- unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
- unsigned PadTo = 0) override;
- unsigned emitInt8(unsigned char Value) override;
- unsigned emitBytes(StringRef Data) override;
-};
-
-/// SizeReporterAsmStreamer - Only reports the size of the streamed objects.
-class SizeReporterAsmStreamer : public AsmStreamerBase {
-public:
- SizeReporterAsmStreamer(const AsmPrinter *AP) : AsmStreamerBase(AP) {}
- unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
- unsigned PadTo = 0) override;
- unsigned emitInt8(unsigned char Value) override;
- unsigned emitBytes(StringRef Data) override;
-};
-
//===--------------------------------------------------------------------===//
/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a
/// Dwarf abbreviation.
@@ -286,25 +243,6 @@ public:
};
//===--------------------------------------------------------------------===//
-/// \brief A signature reference to a type unit.
-class DIETypeSignature {
- const DwarfTypeUnit *Unit;
-
- DIETypeSignature() = delete;
-
-public:
- explicit DIETypeSignature(const DwarfTypeUnit &Unit) : Unit(&Unit) {}
-
- void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
- unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
- assert(Form == dwarf::DW_FORM_ref_sig8);
- return 8;
- }
-
- void print(raw_ostream &O) const;
-};
-
-//===--------------------------------------------------------------------===//
/// DIELocList - Represents a pointer to a location list in the debug_loc
/// section.
//
@@ -350,8 +288,9 @@ private:
/// All values that aren't standard layout (or are larger than 8 bytes)
/// should be stored by reference instead of by value.
typedef AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel,
- DIEDelta *, DIEEntry, DIETypeSignature,
- DIEBlock *, DIELoc *, DIELocList> ValTy;
+ DIEDelta *, DIEEntry, DIEBlock *, DIELoc *,
+ DIELocList>
+ ValTy;
static_assert(sizeof(ValTy) <= sizeof(uint64_t) ||
sizeof(ValTy) <= sizeof(void *),
"Expected all large types to be stored via pointer");
@@ -626,7 +565,7 @@ public:
typedef iterator_range<value_iterator> value_range;
typedef iterator_range<const_value_iterator> const_value_range;
- value_iterator addValue(BumpPtrAllocator &Alloc, DIEValue V) {
+ value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V) {
List.push_back(*new (Alloc) Node(V));
return value_iterator(ListTy::toIterator(List.back()));
}
diff --git a/include/llvm/CodeGen/DIEValue.def b/include/llvm/CodeGen/DIEValue.def
index 2cfae7b608c6a..c5ff4010b2e4a 100644
--- a/include/llvm/CodeGen/DIEValue.def
+++ b/include/llvm/CodeGen/DIEValue.def
@@ -37,7 +37,6 @@ HANDLE_DIEVALUE_SMALL(Expr)
HANDLE_DIEVALUE_SMALL(Label)
HANDLE_DIEVALUE_LARGE(Delta)
HANDLE_DIEVALUE_SMALL(Entry)
-HANDLE_DIEVALUE_SMALL(TypeSignature)
HANDLE_DIEVALUE_LARGE(Block)
HANDLE_DIEVALUE_LARGE(Loc)
HANDLE_DIEVALUE_SMALL(LocList)
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index cc4e37059bb86..4bff48de38e42 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -16,7 +16,6 @@
#define LLVM_CODEGEN_FASTISEL_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -24,6 +23,8 @@
namespace llvm {
+class MachineConstantPool;
+
/// \brief This is a fast-path instruction selection class that generates poor
/// code and doesn't support illegal types or non-trivial lowering, but runs
/// quickly.
@@ -40,12 +41,15 @@ public:
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), Alignment(0) {}
+ IsInAlloca(false), IsReturned(false), IsSwiftSelf(false),
+ IsSwiftError(false), Alignment(0) {}
/// \brief Set CallLoweringInfo attribute flags based on a call instruction
/// and called function attributes.
@@ -448,7 +452,7 @@ protected:
/// \brief Emit an unconditional branch to the given block, unless it is the
/// immediate (fall-through) successor, and update the CFG.
- void fastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL);
+ void fastEmitBranch(MachineBasicBlock *MBB, const DebugLoc &DL);
/// Emit an unconditional branch to \p FalseMBB, obtains the branch weight
/// and adds TrueMBB and FalseMBB to the successor list.
diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h
index f4b6463221432..9b5a3e1ba0500 100644
--- a/include/llvm/CodeGen/FaultMaps.h
+++ b/include/llvm/CodeGen/FaultMaps.h
@@ -10,7 +10,6 @@
#ifndef LLVM_CODEGEN_FAULTMAPS_H
#define LLVM_CODEGEN_FAULTMAPS_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h
index 09a9991912daa..010e34179efc1 100644
--- a/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -72,6 +72,37 @@ public:
/// MBBMap - A mapping from LLVM basic blocks to their machine code entry.
DenseMap<const BasicBlock*, MachineBasicBlock *> MBBMap;
+ typedef SmallVector<unsigned, 1> SwiftErrorVRegs;
+ typedef SmallVector<const Value*, 1> SwiftErrorValues;
+ /// A function can only have a single swifterror argument. And if it does
+ /// have a swifterror argument, it must be the first entry in
+ /// SwiftErrorVals.
+ SwiftErrorValues SwiftErrorVals;
+
+ /// Track the virtual register for each swifterror value in a given basic
+ /// block. Entries in SwiftErrorVRegs have the same ordering as entries
+ /// in SwiftErrorVals.
+ /// Note that another choice that is more straight-forward is to use
+ /// Map<const MachineBasicBlock*, Map<Value*, unsigned/*VReg*/>>. It
+ /// maintains a map from swifterror values to virtual registers for each
+ /// machine basic block. This choice does not require a one-to-one
+ /// correspondence between SwiftErrorValues and SwiftErrorVRegs. But because
+ /// of efficiency concern, we do not choose it.
+ llvm::DenseMap<const MachineBasicBlock*, SwiftErrorVRegs> SwiftErrorMap;
+
+ /// Track the virtual register for each swifterror value at the end of a basic
+ /// block when we need the assignment of a virtual register before the basic
+ /// block is visited. When we actually visit the basic block, we will make
+ /// sure the swifterror value is in the correct virtual register.
+ llvm::DenseMap<const MachineBasicBlock*, SwiftErrorVRegs>
+ SwiftErrorWorklist;
+
+ /// Find the swifterror virtual register in SwiftErrorMap. We will assert
+ /// failure when the value does not exist in swifterror map.
+ unsigned findSwiftErrorVReg(const MachineBasicBlock*, const Value*) const;
+ /// Set the swifterror virtual register in SwiftErrorMap.
+ void setSwiftErrorVReg(const MachineBasicBlock *MBB, const Value*, unsigned);
+
/// ValueMap - Since we emit code for the function a basic block at a time,
/// we must remember which virtual registers hold the values for
/// cross-basic-block values.
@@ -80,15 +111,36 @@ public:
/// Track virtual registers created for exception pointers.
DenseMap<const Value *, unsigned> CatchPadExceptionPointers;
- // Keep track of frame indices allocated for statepoints as they could be used
- // across basic block boundaries.
- // Key of the map is statepoint instruction, value is a map from spilled
- // llvm Value to the optional stack stack slot index.
- // If optional is unspecified it means that we have visited this value
- // but didn't spill it.
- typedef DenseMap<const Value*, Optional<int>> StatepointSpilledValueMapTy;
- DenseMap<const Instruction*, StatepointSpilledValueMapTy>
- StatepointRelocatedValues;
+ /// Keep track of frame indices allocated for statepoints as they could be
+ /// used across basic block boundaries. This struct is more complex than a
+ /// simple map because the stateopint lowering code de-duplicates gc pointers
+ /// based on their SDValue (so %p and (bitcast %p to T) will get the same
+ /// slot), and we track that here.
+
+ struct StatepointSpillMap {
+ typedef DenseMap<const Value *, Optional<int>> SlotMapTy;
+
+ /// Maps uniqued llvm IR values to the slots they were spilled in. If a
+ /// value is mapped to None it means we visited the value but didn't spill
+ /// it (because it was a constant, for instance).
+ SlotMapTy SlotMap;
+
+ /// Maps llvm IR values to the values they were de-duplicated to.
+ DenseMap<const Value *, const Value *> DuplicateMap;
+
+ SlotMapTy::const_iterator find(const Value *V) const {
+ auto DuplIt = DuplicateMap.find(V);
+ if (DuplIt != DuplicateMap.end())
+ V = DuplIt->second;
+ return SlotMap.find(V);
+ }
+
+ SlotMapTy::const_iterator end() const { return SlotMap.end(); }
+ };
+
+ /// Maps gc.statepoint instructions to their corresponding StatepointSpillMap
+ /// instances.
+ DenseMap<const Instruction *, StatepointSpillMap> StatepointSpillMaps;
/// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in
/// the entry block. This allows the allocas to be efficiently referenced
@@ -119,7 +171,7 @@ public:
struct LiveOutInfo {
unsigned NumSignBits : 31;
- bool IsValid : 1;
+ unsigned IsValid : 1;
APInt KnownOne, KnownZero;
LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0),
KnownZero(1, 0) {}
diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h
index 163117b0781cc..e6afcbc8ded28 100644
--- a/include/llvm/CodeGen/GCMetadata.h
+++ b/include/llvm/CodeGen/GCMetadata.h
@@ -40,6 +40,7 @@
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include <memory>
+#include <utility>
namespace llvm {
class AsmPrinter;
@@ -54,7 +55,7 @@ struct GCPoint {
DebugLoc Loc;
GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
- : Kind(K), Label(L), Loc(DL) {}
+ : Kind(K), Label(L), Loc(std::move(DL)) {}
};
/// GCRoot - Metadata for a pointer to an object managed by the garbage
@@ -120,7 +121,7 @@ public:
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
/// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo).
- void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
+ void addSafePoint(GC::PointKind Kind, MCSymbol *Label, const DebugLoc &DL) {
SafePoints.emplace_back(Kind, Label, DL);
}
diff --git a/include/llvm/CodeGen/GlobalISel/CallLowering.h b/include/llvm/CodeGen/GlobalISel/CallLowering.h
new file mode 100644
index 0000000000000..bbd0b6d885938
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -0,0 +1,72 @@
+//===-- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes how to lower LLVM calls to machine code calls.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
+#define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Function.h"
+
+namespace llvm {
+// Forward declarations.
+class MachineIRBuilder;
+class TargetLowering;
+class Value;
+
+class CallLowering {
+ const TargetLowering *TLI;
+ protected:
+ /// Getter for generic TargetLowering class.
+ const TargetLowering *getTLI() const {
+ return TLI;
+ }
+
+ /// Getter for target specific TargetLowering class.
+ template <class XXXTargetLowering>
+ const XXXTargetLowering *getTLI() const {
+ return static_cast<const XXXTargetLowering *>(TLI);
+ }
+ public:
+ CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
+ virtual ~CallLowering() {}
+
+ /// This hook must be implemented to lower outgoing return values, described
+ /// by \p Val, into the specified virtual register \p VReg.
+ /// This hook is used by GlobalISel.
+ ///
+ /// \return True if the lowering succeeds, false otherwise.
+ virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
+ unsigned VReg) const {
+ return false;
+ }
+
+ /// This hook must be implemented to lower the incoming (formal)
+ /// arguments, described by \p Args, for GlobalISel. Each argument
+ /// must end up in the related virtual register described by VRegs.
+ /// In other words, the first argument should end up in VRegs[0],
+ /// the second in VRegs[1], and so on.
+ /// \p MIRBuilder is set to the proper insertion for the argument
+ /// lowering.
+ ///
+ /// \return True if the lowering succeeded, false otherwise.
+ virtual bool
+ lowerFormalArguments(MachineIRBuilder &MIRBuilder,
+ const Function::ArgumentListType &Args,
+ const SmallVectorImpl<unsigned> &VRegs) const {
+ return false;
+ }
+};
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/GISelAccessor.h b/include/llvm/CodeGen/GlobalISel/GISelAccessor.h
new file mode 100644
index 0000000000000..7c5ec9f3adc06
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/GISelAccessor.h
@@ -0,0 +1,33 @@
+//===-- GISelAccessor.h - GISel Accessor ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// This file declares the API to access the various APIs related
+/// to GlobalISel.
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_GISELACCESSOR_H
+#define LLVM_CODEGEN_GLOBALISEL_GISELACCESSOR_H
+
+namespace llvm {
+class CallLowering;
+class RegisterBankInfo;
+
+/// The goal of this helper class is to gather the accessor to all
+/// the APIs related to GlobalISel.
+/// It should be derived to feature an actual accessor to the GISel APIs.
+/// The reason why this is not simply done into the subtarget is to avoid
+/// spreading ifdefs around.
+struct GISelAccessor {
+ virtual ~GISelAccessor() {}
+ virtual const CallLowering *getCallLowering() const { return nullptr;}
+ virtual const RegisterBankInfo *getRegBankInfo() const { return nullptr;}
+};
+} // End namespace llvm;
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h
new file mode 100644
index 0000000000000..833e87493cad1
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -0,0 +1,158 @@
+//===-- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares the IRTranslator pass.
+/// This pass is responsible for translating LLVM IR into MachineInstr.
+/// It uses target hooks to lower the ABI but aside from that, the pass
+/// generated code is generic. This is the default translator used for
+/// GlobalISel.
+///
+/// \todo Replace the comments with actual doxygen comments.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
+#define LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
+
+#include "Types.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+// Forward declarations.
+class BasicBlock;
+class CallLowering;
+class Constant;
+class Instruction;
+class MachineBasicBlock;
+class MachineFunction;
+class MachineInstr;
+class MachineRegisterInfo;
+
+// Technically the pass should run on an hypothetical MachineModule,
+// since it should translate Global into some sort of MachineGlobal.
+// The MachineGlobal should ultimately just be a transfer of ownership of
+// the interesting bits that are relevant to represent a global value.
+// That being said, we could investigate what would it cost to just duplicate
+// the information from the LLVM IR.
+// The idea is that ultimately we would be able to free up the memory used
+// by the LLVM IR as soon as the translation is over.
+class IRTranslator : public MachineFunctionPass {
+public:
+ static char ID;
+
+private:
+ /// Interface used to lower the everything related to calls.
+ const CallLowering *CLI;
+ /// 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;
+
+ DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB;
+
+ /// Methods for translating form LLVM IR to MachineInstr.
+ /// \see ::translate for general information on the translate methods.
+ /// @{
+
+ /// Translate \p Inst into its corresponding MachineInstr instruction(s).
+ /// Insert the newly translated instruction(s) right where the MIRBuilder
+ /// is set.
+ ///
+ /// The general algorithm is:
+ /// 1. Look for a virtual register for each operand or
+ /// create one.
+ /// 2 Update the ValToVReg accordingly.
+ /// 2.alt. For constant arguments, if they are compile time constants,
+ /// produce an immediate in the right operand and do not touch
+ /// ValToReg. Actually we will go with a virtual register for each
+ /// constants because it may be expensive to actually materialize the
+ /// constant. Moreover, if the constant spans on several instructions,
+ /// CSE may not catch them.
+ /// => Update ValToVReg and remember that we saw a constant in Constants.
+ /// We will materialize all the constants in finalize.
+ /// Note: we would need to do something so that we can recognize such operand
+ /// as constants.
+ /// 3. Create the generic instruction.
+ ///
+ /// \return true if the translation succeeded.
+ bool translate(const Instruction &Inst);
+
+ /// Translate \p Inst into a binary operation \p Opcode.
+ /// \pre \p Inst is a binary operation.
+ bool translateBinaryOp(unsigned Opcode, const Instruction &Inst);
+
+ /// Translate branch (br) instruction.
+ /// \pre \p Inst is a branch instruction.
+ bool translateBr(const Instruction &Inst);
+
+ /// Translate return (ret) instruction.
+ /// The target needs to implement CallLowering::lowerReturn for
+ /// this to succeed.
+ /// \pre \p Inst is a return instruction.
+ bool translateReturn(const Instruction &Inst);
+ /// @}
+
+ // Builder for machine instruction a la IRBuilder.
+ // I.e., compared to regular MIBuilder, this one also inserts the instruction
+ // in the current block, it can creates block, etc., basically a kind of
+ // IRBuilder, but for Machine IR.
+ MachineIRBuilder MIRBuilder;
+
+ /// MachineRegisterInfo used to create virtual registers.
+ MachineRegisterInfo *MRI;
+
+ // * 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.
+ // * Clear the different maps.
+ void finalize();
+
+ /// Get the VReg that represents \p Val.
+ /// If such VReg does not exist, it is created.
+ unsigned getOrCreateVReg(const Value &Val);
+
+ /// Get the MachineBasicBlock that represents \p BB.
+ /// If such basic block does not exist, it is created.
+ MachineBasicBlock &getOrCreateBB(const BasicBlock &BB);
+
+public:
+ // Ctor, nothing fancy.
+ IRTranslator();
+
+ const char *getPassName() const override {
+ return "IRTranslator";
+ }
+
+ // Algo:
+ // CallLowering = MF.subtarget.getCallLowering()
+ // F = MF.getParent()
+ // MIRBuilder.reset(MF)
+ // MIRBuilder.getOrCreateBB(F.getEntryBB())
+ // CallLowering->translateArguments(MIRBuilder, F, ValToVReg)
+ // for each bb in F
+ // MIRBuilder.getOrCreateBB(bb)
+ // for each inst in bb
+ // if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence))
+ // report_fatal_error(“Don’t know how to translate input");
+ // finalize()
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+
+} // End namespace llvm.
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
new file mode 100644
index 0000000000000..efdc59a9cddf5
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -0,0 +1,146 @@
+//===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.h - MIBuilder --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares the MachineIRBuilder class.
+/// This is a helper class to build MachineInstr.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
+#define LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
+
+#include "llvm/CodeGen/GlobalISel/Types.h"
+
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/IR/DebugLoc.h"
+
+namespace llvm {
+
+// Forward declarations.
+class MachineFunction;
+class MachineInstr;
+class TargetInstrInfo;
+
+/// Helper class to build MachineInstr.
+/// It keeps internally the insertion point and debug location for all
+/// the new instructions we want to create.
+/// This information can be modify via the related setters.
+class MachineIRBuilder {
+ /// MachineFunction under construction.
+ MachineFunction *MF;
+ /// Information used to access the description of the opcodes.
+ const TargetInstrInfo *TII;
+ /// Debug location to be set to any instruction we create.
+ DebugLoc DL;
+
+ /// Fields describing the insertion point.
+ /// @{
+ MachineBasicBlock *MBB;
+ MachineInstr *MI;
+ bool Before;
+ /// @}
+
+ const TargetInstrInfo &getTII() {
+ assert(TII && "TargetInstrInfo is not set");
+ return *TII;
+ }
+
+public:
+ /// Getter for the function we currently build.
+ MachineFunction &getMF() {
+ assert(MF && "MachineFunction is not set");
+ return *MF;
+ }
+
+ /// Getter for the basic block we currently build.
+ MachineBasicBlock &getMBB() {
+ assert(MBB && "MachineBasicBlock is not set");
+ return *MBB;
+ }
+
+ /// Current insertion point for new instructions.
+ MachineBasicBlock::iterator getInsertPt();
+
+ /// Setters for the insertion point.
+ /// @{
+ /// Set the MachineFunction where to build instructions.
+ void setMF(MachineFunction &);
+
+ /// Set the insertion point to the beginning (\p Beginning = true) or end
+ /// (\p Beginning = false) of \p MBB.
+ /// \pre \p MBB must be contained by getMF().
+ void setMBB(MachineBasicBlock &MBB, bool Beginning = false);
+
+ /// Set the insertion point to before (\p Before = true) or after
+ /// (\p Before = false) \p MI.
+ /// \pre MI must be in getMF().
+ void setInstr(MachineInstr &MI, bool Before = false);
+ /// @}
+
+ /// Set the debug location to \p DL for all the next build instructions.
+ void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
+
+ /// Build and insert <empty> = \p Opcode [\p Ty] <empty>.
+ /// \p Ty is the type of the instruction if \p Opcode describes
+ /// a generic machine instruction. \p Ty must be nullptr if \p Opcode
+ /// does not describe a generic instruction.
+ /// The insertion point is the one set by the last call of either
+ /// setBasicBlock or setMI.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Ty == nullptr or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, Type *Ty);
+
+ /// Build and insert <empty> = \p Opcode [\p Ty] \p BB.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Ty == nullptr or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, Type *Ty, MachineBasicBlock &BB);
+
+ /// Build and insert \p Res<def> = \p Opcode [\p Ty] \p Op0, \p Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Ty == nullptr or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, Type *Ty, unsigned Res,
+ unsigned Op0, unsigned Op1);
+
+ /// Build and insert \p Res<def> = \p Opcode \p Op0, \p Op1.
+ /// I.e., instruction with a non-generic opcode.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre not isPreISelGenericOpcode(\p Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, unsigned Res, unsigned Op0,
+ unsigned Op1);
+
+ /// Build and insert \p Res<def> = \p Opcode \p Op0.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre not isPreISelGenericOpcode(\p Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, unsigned Res, unsigned Op0);
+
+ /// Build and insert <empty> = \p Opcode <empty>.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre not isPreISelGenericOpcode(\p Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode);
+};
+
+} // End namespace llvm.
+#endif // LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
new file mode 100644
index 0000000000000..b393744e67cb6
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
@@ -0,0 +1,614 @@
+//== llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file describes the interface of the MachineFunctionPass
+/// responsible for assigning the generic virtual registers to register bank.
+
+/// By default, the reg bank selector relies on local decisions to
+/// assign the register bank. In other words, it looks at one instruction
+/// at a time to decide where the operand of that instruction should live.
+///
+/// At higher optimization level, we could imagine that the reg bank selector
+/// would use more global analysis and do crazier thing like duplicating
+/// instructions and so on. This is future work.
+///
+/// For now, the pass uses a greedy algorithm to decide where the operand
+/// of an instruction should live. It asks the target which banks may be
+/// used for each operand of the instruction and what is the cost. Then,
+/// it chooses the solution which minimize the cost of the instruction plus
+/// the cost of any move that may be needed to to the values into the right
+/// register bank.
+/// In other words, the cost for an instruction on a register bank RegBank
+/// is: Cost of I on RegBank plus the sum of the cost for bringing the
+/// input operands from their current register bank to RegBank.
+/// Thus, the following formula:
+/// cost(I, RegBank) = cost(I.Opcode, RegBank) +
+/// sum(for each arg in I.arguments: costCrossCopy(arg.RegBank, RegBank))
+///
+/// E.g., Let say we are assigning the register bank for the instruction
+/// defining v2.
+/// v0(A_REGBANK) = ...
+/// v1(A_REGBANK) = ...
+/// v2 = G_ADD i32 v0, v1 <-- MI
+///
+/// The target may say it can generate G_ADD i32 on register bank A and B
+/// with a cost of respectively 5 and 1.
+/// Then, let say the cost of a cross register bank copies from A to B is 1.
+/// The reg bank selector would compare the following two costs:
+/// cost(MI, A_REGBANK) = cost(G_ADD, A_REGBANK) + cost(v0.RegBank, A_REGBANK) +
+/// cost(v1.RegBank, A_REGBANK)
+/// = 5 + cost(A_REGBANK, A_REGBANK) + cost(A_REGBANK,
+/// A_REGBANK)
+/// = 5 + 0 + 0 = 5
+/// cost(MI, B_REGBANK) = cost(G_ADD, B_REGBANK) + cost(v0.RegBank, B_REGBANK) +
+/// cost(v1.RegBank, B_REGBANK)
+/// = 1 + cost(A_REGBANK, B_REGBANK) + cost(A_REGBANK,
+/// B_REGBANK)
+/// = 1 + 1 + 1 = 3
+/// Therefore, in this specific example, the reg bank selector would choose
+/// bank B for MI.
+/// v0(A_REGBANK) = ...
+/// v1(A_REGBANK) = ...
+/// tmp0(B_REGBANK) = COPY v0
+/// tmp1(B_REGBANK) = COPY v1
+/// v2(B_REGBANK) = G_ADD i32 tmp0, tmp1
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
+#define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+// Forward declarations.
+class BlockFrequency;
+class MachineBranchProbabilityInfo;
+class MachineBlockFrequencyInfo;
+class MachineRegisterInfo;
+class TargetRegisterInfo;
+
+/// This pass implements the reg bank selector pass used in the GlobalISel
+/// pipeline. At the end of this pass, all register operands have been assigned
+class RegBankSelect : public MachineFunctionPass {
+public:
+ static char ID;
+
+ /// List of the modes supported by the RegBankSelect pass.
+ enum Mode {
+ /// Assign the register banks as fast as possible (default).
+ Fast,
+ /// Greedily minimize the cost of assigning register banks.
+ /// This should produce code of greater quality, but will
+ /// require more compile time.
+ Greedy
+ };
+
+ /// Abstract class used to represent an insertion point in a CFG.
+ /// This class records an insertion point and materializes it on
+ /// demand.
+ /// It allows to reason about the frequency of this insertion point,
+ /// without having to logically materialize it (e.g., on an edge),
+ /// before we actually need to insert something.
+ class InsertPoint {
+ protected:
+ /// Tell if the insert point has already been materialized.
+ bool WasMaterialized = false;
+ /// Materialize the insertion point.
+ ///
+ /// If isSplit() is true, this involves actually splitting
+ /// the block or edge.
+ ///
+ /// \post getPointImpl() returns a valid iterator.
+ /// \post getInsertMBBImpl() returns a valid basic block.
+ /// \post isSplit() == false ; no more splitting should be required.
+ virtual void materialize() = 0;
+
+ /// Return the materialized insertion basic block.
+ /// Code will be inserted into that basic block.
+ ///
+ /// \pre ::materialize has been called.
+ virtual MachineBasicBlock &getInsertMBBImpl() = 0;
+
+ /// Return the materialized insertion point.
+ /// Code will be inserted before that point.
+ ///
+ /// \pre ::materialize has been called.
+ virtual MachineBasicBlock::iterator getPointImpl() = 0;
+
+ public:
+ virtual ~InsertPoint() {}
+
+ /// The first call to this method will cause the splitting to
+ /// happen if need be, then sub sequent calls just return
+ /// the iterator to that point. I.e., no more splitting will
+ /// occur.
+ ///
+ /// \return The iterator that should be used with
+ /// MachineBasicBlock::insert. I.e., additional code happens
+ /// before that point.
+ MachineBasicBlock::iterator getPoint() {
+ if (!WasMaterialized) {
+ WasMaterialized = true;
+ assert(canMaterialize() && "Impossible to materialize this point");
+ materialize();
+ }
+ // When we materialized the point we should have done the splitting.
+ assert(!isSplit() && "Wrong pre-condition");
+ return getPointImpl();
+ }
+
+ /// The first call to this method will cause the splitting to
+ /// happen if need be, then sub sequent calls just return
+ /// the basic block that contains the insertion point.
+ /// I.e., no more splitting will occur.
+ ///
+ /// \return The basic block should be used with
+ /// MachineBasicBlock::insert and ::getPoint. The new code should
+ /// happen before that point.
+ MachineBasicBlock &getInsertMBB() {
+ if (!WasMaterialized) {
+ WasMaterialized = true;
+ assert(canMaterialize() && "Impossible to materialize this point");
+ materialize();
+ }
+ // When we materialized the point we should have done the splitting.
+ assert(!isSplit() && "Wrong pre-condition");
+ return getInsertMBBImpl();
+ }
+
+ /// Insert \p MI in the just before ::getPoint()
+ MachineBasicBlock::iterator insert(MachineInstr &MI) {
+ return getInsertMBB().insert(getPoint(), &MI);
+ }
+
+ /// Does this point involve splitting an edge or block?
+ /// As soon as ::getPoint is called and thus, the point
+ /// materialized, the point will not require splitting anymore,
+ /// i.e., this will return false.
+ virtual bool isSplit() const { return false; }
+
+ /// Frequency of the insertion point.
+ /// \p P is used to access the various analysis that will help to
+ /// get that information, like MachineBlockFrequencyInfo. If \p P
+ /// does not contain enough enough to return the actual frequency,
+ /// this returns 1.
+ virtual uint64_t frequency(const Pass &P) const { return 1; }
+
+ /// Check whether this insertion point can be materialized.
+ /// As soon as ::getPoint is called and thus, the point materialized
+ /// calling this method does not make sense.
+ virtual bool canMaterialize() const { return false; }
+ };
+
+ /// Insertion point before or after an instruction.
+ class InstrInsertPoint : public InsertPoint {
+ private:
+ /// Insertion point.
+ MachineInstr &Instr;
+ /// Does the insertion point is before or after Instr.
+ bool Before;
+
+ void materialize() override;
+
+ MachineBasicBlock::iterator getPointImpl() override {
+ if (Before)
+ return Instr;
+ return Instr.getNextNode() ? *Instr.getNextNode()
+ : Instr.getParent()->end();
+ }
+
+ MachineBasicBlock &getInsertMBBImpl() override {
+ return *Instr.getParent();
+ }
+
+ public:
+ /// Create an insertion point before (\p Before=true) or after \p Instr.
+ InstrInsertPoint(MachineInstr &Instr, bool Before = true);
+ bool isSplit() const override;
+ uint64_t frequency(const Pass &P) const override;
+
+ // Worst case, we need to slice the basic block, but that is still doable.
+ bool canMaterialize() const override { return true; }
+ };
+
+ /// Insertion point at the beginning or end of a basic block.
+ class MBBInsertPoint : public InsertPoint {
+ private:
+ /// Insertion point.
+ MachineBasicBlock &MBB;
+ /// Does the insertion point is at the beginning or end of MBB.
+ bool Beginning;
+
+ void materialize() override { /*Nothing to do to materialize*/
+ }
+
+ MachineBasicBlock::iterator getPointImpl() override {
+ return Beginning ? MBB.begin() : MBB.end();
+ }
+
+ MachineBasicBlock &getInsertMBBImpl() override { return MBB; }
+
+ public:
+ MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true)
+ : InsertPoint(), MBB(MBB), Beginning(Beginning) {
+ // If we try to insert before phis, we should use the insertion
+ // points on the incoming edges.
+ assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) &&
+ "Invalid beginning point");
+ // If we try to insert after the terminators, we should use the
+ // points on the outcoming edges.
+ assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
+ "Invalid end point");
+ }
+ bool isSplit() const override { return false; }
+ uint64_t frequency(const Pass &P) const override;
+ bool canMaterialize() const override { return true; };
+ };
+
+ /// Insertion point on an edge.
+ class EdgeInsertPoint : public InsertPoint {
+ private:
+ /// Source of the edge.
+ MachineBasicBlock &Src;
+ /// Destination of the edge.
+ /// After the materialization is done, this hold the basic block
+ /// that resulted from the splitting.
+ MachineBasicBlock *DstOrSplit;
+ /// P is used to update the analysis passes as applicable.
+ Pass &P;
+
+ void materialize() override;
+
+ MachineBasicBlock::iterator getPointImpl() override {
+ // DstOrSplit should be the Split block at this point.
+ // I.e., it should have one predecessor, Src, and one successor,
+ // the original Dst.
+ assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) &&
+ DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 &&
+ "Did not split?!");
+ return DstOrSplit->begin();
+ }
+
+ MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; }
+
+ public:
+ EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P)
+ : InsertPoint(), Src(Src), DstOrSplit(&Dst), P(P) {}
+ bool isSplit() const override {
+ return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
+ }
+ uint64_t frequency(const Pass &P) const override;
+ bool canMaterialize() const override;
+ };
+
+ /// Struct used to represent the placement of a repairing point for
+ /// a given operand.
+ class RepairingPlacement {
+ public:
+ /// Define the kind of action this repairing needs.
+ enum RepairingKind {
+ /// Nothing to repair, just drop this action.
+ None,
+ /// Reparing code needs to happen before InsertPoints.
+ Insert,
+ /// (Re)assign the register bank of the operand.
+ Reassign,
+ /// Mark this repairing placement as impossible.
+ Impossible
+ };
+
+ /// Convenient types for a list of insertion points.
+ /// @{
+ typedef SmallVector<std::unique_ptr<InsertPoint>, 2> InsertionPoints;
+ typedef InsertionPoints::iterator insertpt_iterator;
+ typedef InsertionPoints::const_iterator const_insertpt_iterator;
+ /// @}
+
+ private:
+ /// Kind of repairing.
+ RepairingKind Kind;
+ /// Index of the operand that will be repaired.
+ unsigned OpIdx;
+ /// Are all the insert points materializeable?
+ bool CanMaterialize;
+ /// Is there any of the insert points needing splitting?
+ bool HasSplit;
+ /// Insertion point for the repair code.
+ /// The repairing code needs to happen just before these points.
+ InsertionPoints InsertPoints;
+ /// Some insertion points may need to update the liveness and such.
+ Pass &P;
+
+ public:
+ /// Create a repairing placement for the \p OpIdx-th operand of
+ /// \p MI. \p TRI is used to make some checks on the register aliases
+ /// if the machine operand is a physical register. \p P is used to
+ /// to update liveness information and such when materializing the
+ /// points.
+ RepairingPlacement(MachineInstr &MI, unsigned OpIdx,
+ const TargetRegisterInfo &TRI, Pass &P,
+ RepairingKind Kind = RepairingKind::Insert);
+
+ /// Getters.
+ /// @{
+ RepairingKind getKind() const { return Kind; }
+ unsigned getOpIdx() const { return OpIdx; }
+ bool canMaterialize() const { return CanMaterialize; }
+ bool hasSplit() { return HasSplit; }
+ /// @}
+
+ /// Overloaded methods to add an insertion point.
+ /// @{
+ /// Add a MBBInsertionPoint to the list of InsertPoints.
+ void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
+ /// Add a InstrInsertionPoint to the list of InsertPoints.
+ void addInsertPoint(MachineInstr &MI, bool Before);
+ /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints.
+ void addInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst);
+ /// Add an InsertPoint to the list of insert points.
+ /// This method takes the ownership of &\p Point.
+ void addInsertPoint(InsertPoint &Point);
+ /// @}
+
+ /// Accessors related to the insertion points.
+ /// @{
+ insertpt_iterator begin() { return InsertPoints.begin(); }
+ insertpt_iterator end() { return InsertPoints.end(); }
+
+ const_insertpt_iterator begin() const { return InsertPoints.begin(); }
+ const_insertpt_iterator end() const { return InsertPoints.end(); }
+
+ unsigned getNumInsertPoints() const { return InsertPoints.size(); }
+ /// @}
+
+ /// Change the type of this repairing placement to \p NewKind.
+ /// It is not possible to switch a repairing placement to the
+ /// RepairingKind::Insert. There is no fundamental problem with
+ /// that, but no uses as well, so do not support it for now.
+ ///
+ /// \pre NewKind != RepairingKind::Insert
+ /// \post getKind() == NewKind
+ void switchTo(RepairingKind NewKind) {
+ assert(NewKind != Kind && "Already of the right Kind");
+ Kind = NewKind;
+ InsertPoints.clear();
+ CanMaterialize = NewKind != RepairingKind::Impossible;
+ HasSplit = false;
+ assert(NewKind != RepairingKind::Insert &&
+ "We would need more MI to switch to Insert");
+ }
+ };
+
+private:
+ /// Helper class used to represent the cost for mapping an instruction.
+ /// When mapping an instruction, we may introduce some repairing code.
+ /// In most cases, the repairing code is local to the instruction,
+ /// thus, we can omit the basic block frequency from the cost.
+ /// However, some alternatives may produce non-local cost, e.g., when
+ /// repairing a phi, and thus we then need to scale the local cost
+ /// to the non-local cost. This class does this for us.
+ /// \note: We could simply always scale the cost. The problem is that
+ /// there are higher chances that we saturate the cost easier and end
+ /// up having the same cost for actually different alternatives.
+ /// Another option would be to use APInt everywhere.
+ class MappingCost {
+ private:
+ /// Cost of the local instructions.
+ /// This cost is free of basic block frequency.
+ uint64_t LocalCost;
+ /// Cost of the non-local instructions.
+ /// This cost should include the frequency of the related blocks.
+ uint64_t NonLocalCost;
+ /// Frequency of the block where the local instructions live.
+ uint64_t LocalFreq;
+
+ MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq)
+ : LocalCost(LocalCost), NonLocalCost(NonLocalCost),
+ LocalFreq(LocalFreq) {}
+
+ /// Check if this cost is saturated.
+ bool isSaturated() const;
+
+ public:
+ /// Create a MappingCost assuming that most of the instructions
+ /// will occur in a basic block with \p LocalFreq frequency.
+ MappingCost(const BlockFrequency &LocalFreq);
+
+ /// Add \p Cost to the local cost.
+ /// \return true if this cost is saturated, false otherwise.
+ bool addLocalCost(uint64_t Cost);
+
+ /// Add \p Cost to the non-local cost.
+ /// Non-local cost should reflect the frequency of their placement.
+ /// \return true if this cost is saturated, false otherwise.
+ bool addNonLocalCost(uint64_t Cost);
+
+ /// Saturate the cost to the maximal representable value.
+ void saturate();
+
+ /// Return an instance of MappingCost that represents an
+ /// impossible mapping.
+ static MappingCost ImpossibleCost();
+
+ /// Check if this is less than \p Cost.
+ bool operator<(const MappingCost &Cost) const;
+ /// Check if this is equal to \p Cost.
+ bool operator==(const MappingCost &Cost) const;
+ /// Check if this is not equal to \p Cost.
+ bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); }
+ /// Check if this is greater than \p Cost.
+ bool operator>(const MappingCost &Cost) const {
+ return *this != Cost && Cost < *this;
+ }
+ };
+
+ /// Interface to the target lowering info related
+ /// to register banks.
+ const RegisterBankInfo *RBI;
+
+ /// MRI contains all the register class/bank information that this
+ /// pass uses and updates.
+ MachineRegisterInfo *MRI;
+
+ /// Information on the register classes for the current function.
+ const TargetRegisterInfo *TRI;
+
+ /// Get the frequency of blocks.
+ /// This is required for non-fast mode.
+ MachineBlockFrequencyInfo *MBFI;
+
+ /// Get the frequency of the edges.
+ /// This is required for non-fast mode.
+ MachineBranchProbabilityInfo *MBPI;
+
+ /// Helper class used for every code morphing.
+ MachineIRBuilder MIRBuilder;
+
+ /// Optimization mode of the pass.
+ Mode OptMode;
+
+ /// Assign the register bank of each operand of \p MI.
+ void assignInstr(MachineInstr &MI);
+
+ /// Initialize the field members using \p MF.
+ void init(MachineFunction &MF);
+
+ /// Check if \p Reg is already assigned what is described by \p ValMapping.
+ /// \p OnlyAssign == true means that \p Reg just needs to be assigned a
+ /// register bank. I.e., no repairing is necessary to have the
+ /// assignment match.
+ bool assignmentMatch(unsigned Reg,
+ const RegisterBankInfo::ValueMapping &ValMapping,
+ bool &OnlyAssign) const;
+
+ /// Insert repairing code for \p Reg as specified by \p ValMapping.
+ /// The repairing placement is specified by \p RepairPt.
+ /// \p NewVRegs contains all the registers required to remap \p Reg.
+ /// In other words, the number of registers in NewVRegs must be equal
+ /// to ValMapping.BreakDown.size().
+ ///
+ /// The transformation could be sketched as:
+ /// \code
+ /// ... = op Reg
+ /// \endcode
+ /// Becomes
+ /// \code
+ /// <NewRegs> = COPY or extract Reg
+ /// ... = op Reg
+ /// \endcode
+ ///
+ /// and
+ /// \code
+ /// Reg = op ...
+ /// \endcode
+ /// Becomes
+ /// \code
+ /// Reg = op ...
+ /// Reg = COPY or build_sequence <NewRegs>
+ /// \endcode
+ ///
+ /// \pre NewVRegs.size() == ValMapping.BreakDown.size()
+ ///
+ /// \note The caller is supposed to do the rewriting of op if need be.
+ /// I.e., Reg = op ... => <NewRegs> = NewOp ...
+ void repairReg(MachineOperand &MO,
+ const RegisterBankInfo::ValueMapping &ValMapping,
+ RegBankSelect::RepairingPlacement &RepairPt,
+ const iterator_range<SmallVectorImpl<unsigned>::const_iterator>
+ &NewVRegs);
+
+ /// Return the cost of the instruction needed to map \p MO to \p ValMapping.
+ /// The cost is free of basic block frequencies.
+ /// \pre MO.isReg()
+ /// \pre MO is assigned to a register bank.
+ /// \pre ValMapping is a valid mapping for MO.
+ uint64_t
+ getRepairCost(const MachineOperand &MO,
+ const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+ /// Find the best mapping for \p MI from \p PossibleMappings.
+ /// \return a reference on the best mapping in \p PossibleMappings.
+ RegisterBankInfo::InstructionMapping &
+ findBestMapping(MachineInstr &MI,
+ RegisterBankInfo::InstructionMappings &PossibleMappings,
+ SmallVectorImpl<RepairingPlacement> &RepairPts);
+
+ /// Compute the cost of mapping \p MI with \p InstrMapping and
+ /// compute the repairing placement for such mapping in \p
+ /// RepairPts.
+ /// \p BestCost is used to specify when the cost becomes too high
+ /// and thus it is not worth computing the RepairPts. Moreover if
+ /// \p BestCost == nullptr, the mapping cost is actually not
+ /// computed.
+ MappingCost
+ computeMapping(MachineInstr &MI,
+ const RegisterBankInfo::InstructionMapping &InstrMapping,
+ SmallVectorImpl<RepairingPlacement> &RepairPts,
+ const MappingCost *BestCost = nullptr);
+
+ /// When \p RepairPt involves splitting to repair \p MO for the
+ /// given \p ValMapping, try to change the way we repair such that
+ /// the splitting is not required anymore.
+ ///
+ /// \pre \p RepairPt.hasSplit()
+ /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx())
+ /// \pre \p ValMapping is the mapping of \p MO for MO.getParent()
+ /// that implied \p RepairPt.
+ void tryAvoidingSplit(RegBankSelect::RepairingPlacement &RepairPt,
+ const MachineOperand &MO,
+ const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+ /// Apply \p Mapping to \p MI. \p RepairPts represents the different
+ /// mapping action that need to happen for the mapping to be
+ /// applied.
+ void applyMapping(MachineInstr &MI,
+ const RegisterBankInfo::InstructionMapping &InstrMapping,
+ SmallVectorImpl<RepairingPlacement> &RepairPts);
+
+public:
+ /// Create a RegBankSelect pass with the specified \p RunningMode.
+ RegBankSelect(Mode RunningMode = Fast);
+
+ const char *getPassName() const override {
+ return "RegBankSelect";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ /// Walk through \p MF and assign a register bank to every virtual register
+ /// that are still mapped to nothing.
+ /// The target needs to provide a RegisterBankInfo and in particular
+ /// override RegisterBankInfo::getInstrMapping.
+ ///
+ /// Simplified algo:
+ /// \code
+ /// RBI = MF.subtarget.getRegBankInfo()
+ /// MIRBuilder.setMF(MF)
+ /// for each bb in MF
+ /// for each inst in bb
+ /// MIRBuilder.setInstr(inst)
+ /// MappingCosts = RBI.getMapping(inst);
+ /// Idx = findIdxOfMinCost(MappingCosts)
+ /// CurRegBank = MappingCosts[Idx].RegBank
+ /// MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
+ /// for each argument in inst
+ /// if (CurRegBank != argument.RegBank)
+ /// ArgReg = argument.getReg()
+ /// Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
+ /// MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
+ /// inst.getOperand(argument.getOperandNo()).setReg(Tmp)
+ /// \endcode
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h
new file mode 100644
index 0000000000000..e886382fd8e83
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h
@@ -0,0 +1,101 @@
+//==-- llvm/CodeGen/GlobalISel/RegisterBank.h - Register Bank ----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file declares the API of register banks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANK_H
+#define LLVM_CODEGEN_GLOBALISEL_REGBANK_H
+
+#include "llvm/ADT/BitVector.h"
+
+namespace llvm {
+// Forward declarations.
+class RegisterBankInfo;
+class raw_ostream;
+class TargetRegisterClass;
+class TargetRegisterInfo;
+
+/// This class implements the register bank concept.
+/// Two instances of RegisterBank must have different ID.
+/// This property is enforced by the RegisterBankInfo class.
+class RegisterBank {
+private:
+ unsigned ID;
+ const char *Name;
+ unsigned Size;
+ BitVector ContainedRegClasses;
+
+ /// Sentinel value used to recognize register bank not properly
+ /// initialized yet.
+ static const unsigned InvalidID;
+
+ /// Only the RegisterBankInfo can create RegisterBank.
+ /// The default constructor will leave the object in
+ /// an invalid state. I.e. isValid() == false.
+ /// The field must be updated to fix that.
+ RegisterBank();
+
+ friend RegisterBankInfo;
+
+public:
+ /// Get the identifier of this register bank.
+ unsigned getID() const { return ID; }
+
+ /// Get a user friendly name of this register bank.
+ /// Should be used only for debugging purposes.
+ const char *getName() const { return Name; }
+
+ /// Get the maximal size in bits that fits in this register bank.
+ unsigned getSize() const { return Size; }
+
+ /// Check whether this instance is ready to be used.
+ bool isValid() const;
+
+ /// Check if this register bank is valid. In other words,
+ /// if it has been properly constructed.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(const TargetRegisterInfo &TRI) const;
+
+ /// Check whether this register bank covers \p RC.
+ /// In other words, check if this register bank fully covers
+ /// the registers that \p RC contains.
+ /// \pre isValid()
+ bool covers(const TargetRegisterClass &RC) const;
+
+ /// Check whether \p OtherRB is the same as this.
+ bool operator==(const RegisterBank &OtherRB) const;
+ bool operator!=(const RegisterBank &OtherRB) const {
+ return !this->operator==(OtherRB);
+ }
+
+ /// Dump the register mask on dbgs() stream.
+ /// The dump is verbose.
+ void dump(const TargetRegisterInfo *TRI = nullptr) const;
+
+ /// Print the register mask on OS.
+ /// If IsForDebug is false, then only the name of the register bank
+ /// is printed. Otherwise, all the fields are printing.
+ /// TRI is then used to print the name of the register classes that
+ /// this register bank covers.
+ void print(raw_ostream &OS, bool IsForDebug = false,
+ const TargetRegisterInfo *TRI = nullptr) const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const RegisterBank &RegBank) {
+ RegBank.print(OS);
+ return OS;
+}
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
new file mode 100644
index 0000000000000..19d170365858b
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
@@ -0,0 +1,602 @@
+//==-- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ----------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file declares the API for the register bank info.
+/// This API is responsible for handling the register banks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
+#define LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
+#include "llvm/CodeGen/MachineValueType.h" // For SimpleValueType.
+#include "llvm/Support/ErrorHandling.h"
+
+#include <cassert>
+#include <memory> // For unique_ptr.
+
+namespace llvm {
+class MachineInstr;
+class MachineRegisterInfo;
+class TargetInstrInfo;
+class TargetRegisterInfo;
+class raw_ostream;
+
+/// Holds all the information related to register banks.
+class RegisterBankInfo {
+public:
+ /// Helper struct that represents how a value is partially mapped
+ /// into a register.
+ /// The StartIdx and Length represent what region of the orginal
+ /// value this partial mapping covers.
+ /// This can be represented as a Mask of contiguous bit starting
+ /// at StartIdx bit and spanning Length bits.
+ /// StartIdx is the number of bits from the less significant bits.
+ struct PartialMapping {
+ /// Number of bits at which this partial mapping starts in the
+ /// original value. The bits are counted from less significant
+ /// bits to most significant bits.
+ unsigned StartIdx;
+ /// Length of this mapping in bits. This is how many bits this
+ /// partial mapping covers in the original value:
+ /// from StartIdx to StartIdx + Length -1.
+ unsigned Length;
+ /// Register bank where the partial value lives.
+ const RegisterBank *RegBank;
+
+ PartialMapping() = default;
+
+ /// Provide a shortcut for quickly building PartialMapping.
+ PartialMapping(unsigned StartIdx, unsigned Length,
+ const RegisterBank &RegBank)
+ : StartIdx(StartIdx), Length(Length), RegBank(&RegBank) {}
+
+ /// \return the index of in the original value of the most
+ /// significant bit that this partial mapping covers.
+ unsigned getHighBitIdx() const { return StartIdx + Length - 1; }
+
+ /// Print this partial mapping on dbgs() stream.
+ void dump() const;
+
+ /// Print this partial mapping on \p OS;
+ void print(raw_ostream &OS) const;
+
+ /// Check that the Mask is compatible with the RegBank.
+ /// Indeed, if the RegBank cannot accomadate the "active bits" of the mask,
+ /// there is no way this mapping is valid.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify() const;
+ };
+
+ /// Helper struct that represents how a value is mapped through
+ /// different register banks.
+ struct ValueMapping {
+ /// How the value is broken down between the different register banks.
+ SmallVector<PartialMapping, 2> BreakDown;
+
+ /// Verify that this mapping makes sense for a value of \p ExpectedBitWidth.
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(unsigned ExpectedBitWidth) const;
+
+ /// Print this on dbgs() stream.
+ void dump() const;
+
+ /// Print this on \p OS;
+ void print(raw_ostream &OS) const;
+ };
+
+ /// Helper class that represents how the value of an instruction may be
+ /// mapped and what is the related cost of such mapping.
+ class InstructionMapping {
+ /// Identifier of the mapping.
+ /// This is used to communicate between the target and the optimizers
+ /// which mapping should be realized.
+ unsigned ID;
+ /// Cost of this mapping.
+ unsigned Cost;
+ /// Mapping of all the operands.
+ std::unique_ptr<ValueMapping[]> OperandsMapping;
+ /// Number of operands.
+ unsigned NumOperands;
+
+ ValueMapping &getOperandMapping(unsigned i) {
+ assert(i < getNumOperands() && "Out of bound operand");
+ return OperandsMapping[i];
+ }
+
+ public:
+ /// Constructor for the mapping of an instruction.
+ /// \p NumOperands must be equal to number of all the operands of
+ /// the related instruction.
+ /// The rationale is that it is more efficient for the optimizers
+ /// to be able to assume that the mapping of the ith operand is
+ /// at the index i.
+ ///
+ /// \pre ID != InvalidMappingID
+ InstructionMapping(unsigned ID, unsigned Cost, unsigned NumOperands)
+ : ID(ID), Cost(Cost), NumOperands(NumOperands) {
+ assert(getID() != InvalidMappingID &&
+ "Use the default constructor for invalid mapping");
+ OperandsMapping.reset(new ValueMapping[getNumOperands()]);
+ }
+
+ /// Default constructor.
+ /// Use this constructor to express that the mapping is invalid.
+ InstructionMapping() : ID(InvalidMappingID), Cost(0), NumOperands(0) {}
+
+ /// Get the cost.
+ unsigned getCost() const { return Cost; }
+
+ /// Get the ID.
+ unsigned getID() const { return ID; }
+
+ /// Get the number of operands.
+ unsigned getNumOperands() const { return NumOperands; }
+
+ /// Get the value mapping of the ith operand.
+ const ValueMapping &getOperandMapping(unsigned i) const {
+ return const_cast<InstructionMapping *>(this)->getOperandMapping(i);
+ }
+
+ /// Get the value mapping of the ith operand.
+ void setOperandMapping(unsigned i, const ValueMapping &ValMapping) {
+ getOperandMapping(i) = ValMapping;
+ }
+
+ /// Check whether this object is valid.
+ /// This is a lightweight check for obvious wrong instance.
+ bool isValid() const { return getID() != InvalidMappingID; }
+
+ /// Set the operand mapping for the \p OpIdx-th operand.
+ /// The mapping will consist of only one element in the break down list.
+ /// This element will map to \p RegBank and fully define a mask, whose
+ /// bitwidth matches the size of \p MaskSize.
+ void setOperandMapping(unsigned OpIdx, unsigned MaskSize,
+ const RegisterBank &RegBank);
+
+ /// Verifiy that this mapping makes sense for \p MI.
+ /// \pre \p MI must be connected to a MachineFunction.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(const MachineInstr &MI) const;
+
+ /// Print this on dbgs() stream.
+ void dump() const;
+
+ /// Print this on \p OS;
+ void print(raw_ostream &OS) const;
+ };
+
+ /// Convenient type to represent the alternatives for mapping an
+ /// instruction.
+ /// \todo When we move to TableGen this should be an array ref.
+ typedef SmallVector<InstructionMapping, 4> InstructionMappings;
+
+ /// Helper class use to get/create the virtual registers that will be used
+ /// to replace the MachineOperand when applying a mapping.
+ class OperandsMapper {
+ /// The OpIdx-th cell contains the index in NewVRegs where the VRegs of the
+ /// OpIdx-th operand starts. -1 means we do not have such mapping yet.
+ std::unique_ptr<int[]> OpToNewVRegIdx;
+ /// Hold the registers that will be used to map MI with InstrMapping.
+ SmallVector<unsigned, 8> NewVRegs;
+ /// Current MachineRegisterInfo, used to create new virtual registers.
+ MachineRegisterInfo &MRI;
+ /// Instruction being remapped.
+ MachineInstr &MI;
+ /// New mapping of the instruction.
+ const InstructionMapping &InstrMapping;
+
+ /// Constant value identifying that the index in OpToNewVRegIdx
+ /// for an operand has not been set yet.
+ static const int DontKnowIdx;
+
+ /// Get the range in NewVRegs to store all the partial
+ /// values for the \p OpIdx-th operand.
+ ///
+ /// \return The iterator range for the space created.
+ //
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ iterator_range<SmallVectorImpl<unsigned>::iterator>
+ getVRegsMem(unsigned OpIdx);
+
+ /// Get the end iterator for a range starting at \p StartIdx and
+ /// spannig \p NumVal in NewVRegs.
+ /// \pre StartIdx + NumVal <= NewVRegs.size()
+ SmallVectorImpl<unsigned>::const_iterator
+ getNewVRegsEnd(unsigned StartIdx, unsigned NumVal) const;
+ SmallVectorImpl<unsigned>::iterator getNewVRegsEnd(unsigned StartIdx,
+ unsigned NumVal);
+
+ public:
+ /// Create an OperandsMapper that will hold the information to apply \p
+ /// InstrMapping to \p MI.
+ /// \pre InstrMapping.verify(MI)
+ OperandsMapper(MachineInstr &MI, const InstructionMapping &InstrMapping,
+ MachineRegisterInfo &MRI);
+
+ /// Getters.
+ /// @{
+ /// The MachineInstr being remapped.
+ MachineInstr &getMI() const { return MI; }
+
+ /// The final mapping of the instruction.
+ const InstructionMapping &getInstrMapping() const { return InstrMapping; }
+ /// @}
+
+ /// 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.
+ ///
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ ///
+ /// \post All the partial mapping of the \p OpIdx-th operand have been
+ /// assigned a new virtual register.
+ void createVRegs(unsigned OpIdx);
+
+ /// Set the virtual register of the \p PartialMapIdx-th partial mapping of
+ /// the OpIdx-th operand to \p NewVReg.
+ ///
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ /// \pre getInstrMapping().getOperandMapping(OpIdx).BreakDown.size() >
+ /// PartialMapIdx
+ /// \pre NewReg != 0
+ ///
+ /// \post the \p PartialMapIdx-th register of the value mapping of the \p
+ /// OpIdx-th operand has been set.
+ void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, unsigned NewVReg);
+
+ /// Get all the virtual registers required to map the \p OpIdx-th operand of
+ /// the instruction.
+ ///
+ /// This return an empty range when createVRegs or setVRegs has not been
+ /// called.
+ /// The iterator may be invalidated by a call to setVRegs or createVRegs.
+ ///
+ /// When \p ForDebug is true, we will not check that the list of new virtual
+ /// registers does not contain uninitialized values.
+ ///
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ /// \pre ForDebug || All partial mappings have been set a register
+ iterator_range<SmallVectorImpl<unsigned>::const_iterator>
+ getVRegs(unsigned OpIdx, bool ForDebug = false) const;
+
+ /// Print this operands mapper on dbgs() stream.
+ void dump() const;
+
+ /// Print this operands mapper on \p OS stream.
+ void print(raw_ostream &OS, bool ForDebug = false) const;
+ };
+
+protected:
+ /// Hold the set of supported register banks.
+ std::unique_ptr<RegisterBank[]> RegBanks;
+ /// Total number of register banks.
+ unsigned NumRegBanks;
+
+ /// Mapping from MVT::SimpleValueType to register banks.
+ std::unique_ptr<const RegisterBank *[]> VTToRegBank;
+
+ /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
+ /// RegisterBank instances.
+ ///
+ /// \note For the verify method to succeed all the \p NumRegBanks
+ /// must be initialized by createRegisterBank and updated with
+ /// addRegBankCoverage RegisterBank.
+ RegisterBankInfo(unsigned NumRegBanks);
+
+ /// This constructor is meaningless.
+ /// It just provides a default constructor that can be used at link time
+ /// when GlobalISel is not built.
+ /// That way, targets can still inherit from this class without doing
+ /// crazy gymnastic to avoid link time failures.
+ /// \note That works because the constructor is inlined.
+ RegisterBankInfo() {
+ llvm_unreachable("This constructor should not be executed");
+ }
+
+ /// Create a new register bank with the given parameter and add it
+ /// to RegBanks.
+ /// \pre \p ID must not already be used.
+ /// \pre \p ID < NumRegBanks.
+ void createRegisterBank(unsigned ID, const char *Name);
+
+ /// Add \p RCId to the set of register class that the register bank,
+ /// identified \p ID, covers.
+ /// This method transitively adds all the sub classes and the subreg-classes
+ /// of \p RCId to the set of covered register classes.
+ /// It also adjusts the size of the register bank to reflect the maximal
+ /// size of a value that can be hold into that register bank.
+ ///
+ /// If \p AddTypeMapping is true, this method also records what types can
+ /// be mapped to \p ID. Although this done by default, targets may want to
+ /// disable it, espicially if a given type may be mapped on different
+ /// register bank. Indeed, in such case, this method only records the
+ /// first register bank where the type matches.
+ /// This information is only used to provide default mapping
+ /// (see getInstrMappingImpl).
+ ///
+ /// \note This method does *not* add the super classes of \p RCId.
+ /// The rationale is if \p ID covers the registers of \p RCId, that
+ /// does not necessarily mean that \p ID covers the set of registers
+ /// of RCId's superclasses.
+ /// This method does *not* add the superreg classes as well for consistents.
+ /// The expected use is to add the coverage top-down with respect to the
+ /// register hierarchy.
+ ///
+ /// \todo TableGen should just generate the BitSet vector for us.
+ void addRegBankCoverage(unsigned ID, unsigned RCId,
+ const TargetRegisterInfo &TRI,
+ bool AddTypeMapping = true);
+
+ /// Get the register bank identified by \p ID.
+ RegisterBank &getRegBank(unsigned ID) {
+ assert(ID < getNumRegBanks() && "Accessing an unknown register bank");
+ return RegBanks[ID];
+ }
+
+ /// Get the register bank that has been recorded to cover \p SVT.
+ const RegisterBank *getRegBankForType(MVT::SimpleValueType SVT) const {
+ if (!VTToRegBank)
+ return nullptr;
+ assert(SVT < MVT::SimpleValueType::LAST_VALUETYPE && "Out-of-bound access");
+ return VTToRegBank.get()[SVT];
+ }
+
+ /// Record \p RegBank as the register bank that covers \p SVT.
+ /// If a record was already set for \p SVT, the mapping is not
+ /// updated, unless \p Force == true
+ ///
+ /// \post if getRegBankForType(SVT)\@pre == nullptr then
+ /// getRegBankForType(SVT) == &RegBank
+ /// \post if Force == true then getRegBankForType(SVT) == &RegBank
+ void recordRegBankForType(const RegisterBank &RegBank,
+ MVT::SimpleValueType SVT, bool Force = false) {
+ if (!VTToRegBank) {
+ VTToRegBank.reset(
+ new const RegisterBank *[MVT::SimpleValueType::LAST_VALUETYPE]);
+ std::fill(&VTToRegBank[0],
+ &VTToRegBank[MVT::SimpleValueType::LAST_VALUETYPE], nullptr);
+ }
+ assert(SVT < MVT::SimpleValueType::LAST_VALUETYPE && "Out-of-bound access");
+ // If we want to override the mapping or the mapping does not exits yet,
+ // set the register bank for SVT.
+ if (Force || !getRegBankForType(SVT))
+ VTToRegBank.get()[SVT] = &RegBank;
+ }
+
+ /// Try to get the mapping of \p MI.
+ /// See getInstrMapping for more details on what a mapping represents.
+ ///
+ /// Unlike getInstrMapping the returned InstructionMapping may be invalid
+ /// (isValid() == false).
+ /// This means that the target independent code is not smart enough
+ /// to get the mapping of \p MI and thus, the target has to provide the
+ /// information for \p MI.
+ ///
+ /// This implementation is able to get the mapping of:
+ /// - Target specific instructions by looking at the encoding constraints.
+ /// - Any instruction if all the register operands are already been assigned
+ /// a register, a register class, or a register bank.
+ /// - Copies and phis if at least one of the operand has been assigned a
+ /// register, a register class, or a register bank.
+ /// In other words, this method will likely fail to find a mapping for
+ /// any generic opcode that has not been lowered by target specific code.
+ InstructionMapping getInstrMappingImpl(const MachineInstr &MI) const;
+
+ /// Get the register bank for the \p OpIdx-th operand of \p MI form
+ /// the encoding constraints, if any.
+ ///
+ /// \return A register bank that covers the register class of the
+ /// related encoding constraints or nullptr if \p MI did not provide
+ /// enough information to deduce it.
+ const RegisterBank *
+ getRegBankFromConstraints(const MachineInstr &MI, unsigned OpIdx,
+ const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI) const;
+
+ /// Helper method to apply something that is like the default mapping.
+ /// Basically, that means that \p OpdMapper.getMI() is left untouched
+ /// aside from the reassignment of the register operand that have been
+ /// remapped.
+ /// If the mapping of one of the operand spans several registers, this
+ /// method will abort as this is not like a default mapping anymore.
+ ///
+ /// \pre For OpIdx in {0..\p OpdMapper.getMI().getNumOperands())
+ /// the range OpdMapper.getVRegs(OpIdx) is empty or of size 1.
+ static void applyDefaultMapping(const OperandsMapper &OpdMapper);
+
+ /// See ::applyMapping.
+ virtual void applyMappingImpl(const OperandsMapper &OpdMapper) const {
+ llvm_unreachable("The target has to implement that part");
+ }
+
+public:
+ virtual ~RegisterBankInfo() {}
+
+ /// Get the register bank identified by \p ID.
+ const RegisterBank &getRegBank(unsigned ID) const {
+ return const_cast<RegisterBankInfo *>(this)->getRegBank(ID);
+ }
+
+ /// Get the register bank of \p Reg.
+ /// If Reg has not been assigned a register, a register class,
+ /// or a register bank, then this returns nullptr.
+ ///
+ /// \pre Reg != 0 (NoRegister)
+ const RegisterBank *getRegBank(unsigned Reg, const MachineRegisterInfo &MRI,
+ const TargetRegisterInfo &TRI) const;
+
+ /// Get the total number of register banks.
+ unsigned getNumRegBanks() const { return NumRegBanks; }
+
+ /// Get a register bank that covers \p RC.
+ ///
+ /// \pre \p RC is a user-defined register class (as opposed as one
+ /// generated by TableGen).
+ ///
+ /// \note The mapping RC -> RegBank could be built while adding the
+ /// coverage for the register banks. However, we do not do it, because,
+ /// at least for now, we only need this information for register classes
+ /// that are used in the description of instruction. In other words,
+ /// there are just a handful of them and we do not want to waste space.
+ ///
+ /// \todo This should be TableGen'ed.
+ virtual const RegisterBank &
+ getRegBankFromRegClass(const TargetRegisterClass &RC) const {
+ llvm_unreachable("The target must override this method");
+ }
+
+ /// Get the cost of a copy from \p B to \p A, or put differently,
+ /// get the cost of A = COPY B. Since register banks may cover
+ /// different size, \p Size specifies what will be the size in bits
+ /// that will be copied around.
+ ///
+ /// \note Since this is a copy, both registers have the same size.
+ virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B,
+ unsigned Size) const {
+ // Optimistically assume that copies are coalesced. I.e., when
+ // they are on the same bank, they are free.
+ // Otherwise assume a non-zero cost of 1. The targets are supposed
+ // to override that properly anyway if they care.
+ return &A != &B;
+ }
+
+ /// Identifier used when the related instruction mapping instance
+ /// is generated by target independent code.
+ /// Make sure not to use that identifier to avoid possible collision.
+ static const unsigned DefaultMappingID;
+
+ /// Identifier used when the related instruction mapping instance
+ /// is generated by the default constructor.
+ /// Make sure not to use that identifier.
+ static const unsigned InvalidMappingID;
+
+ /// Get the mapping of the different operands of \p MI
+ /// on the register bank.
+ /// This mapping should be the direct translation of \p MI.
+ /// In other words, when \p MI is mapped with the returned mapping,
+ /// only the register banks of the operands of \p MI need to be updated.
+ /// In particular, neither the opcode or the type of \p MI needs to be
+ /// updated for this direct mapping.
+ ///
+ /// The target independent implementation gives a mapping based on
+ /// the register classes for the target specific opcode.
+ /// It uses the ID RegisterBankInfo::DefaultMappingID for that mapping.
+ /// Make sure you do not use that ID for the alternative mapping
+ /// for MI. See getInstrAlternativeMappings for the alternative
+ /// mappings.
+ ///
+ /// For instance, if \p MI is a vector add, the mapping should
+ /// not be a scalarization of the add.
+ ///
+ /// \post returnedVal.verify(MI).
+ ///
+ /// \note If returnedVal does not verify MI, this would probably mean
+ /// that the target does not support that instruction.
+ virtual InstructionMapping getInstrMapping(const MachineInstr &MI) const;
+
+ /// Get the alternative mappings for \p MI.
+ /// Alternative in the sense different from getInstrMapping.
+ virtual InstructionMappings
+ getInstrAlternativeMappings(const MachineInstr &MI) const;
+
+ /// Get the possible mapping for \p MI.
+ /// A mapping defines where the different operands may live and at what cost.
+ /// For instance, let us consider:
+ /// v0(16) = G_ADD <2 x i8> v1, v2
+ /// The possible mapping could be:
+ ///
+ /// {/*ID*/VectorAdd, /*Cost*/1, /*v0*/{(0xFFFF, VPR)}, /*v1*/{(0xFFFF, VPR)},
+ /// /*v2*/{(0xFFFF, VPR)}}
+ /// {/*ID*/ScalarAddx2, /*Cost*/2, /*v0*/{(0x00FF, GPR),(0xFF00, GPR)},
+ /// /*v1*/{(0x00FF, GPR),(0xFF00, GPR)},
+ /// /*v2*/{(0x00FF, GPR),(0xFF00, GPR)}}
+ ///
+ /// \note The first alternative of the returned mapping should be the
+ /// direct translation of \p MI current form.
+ ///
+ /// \post !returnedVal.empty().
+ InstructionMappings getInstrPossibleMappings(const MachineInstr &MI) const;
+
+ /// Apply \p OpdMapper.getInstrMapping() to \p OpdMapper.getMI().
+ /// After this call \p OpdMapper.getMI() may not be valid anymore.
+ /// \p OpdMapper.getInstrMapping().getID() carries the information of
+ /// what has been chosen to map \p OpdMapper.getMI(). This ID is set
+ /// by the various getInstrXXXMapping method.
+ ///
+ /// Therefore, getting the mapping and applying it should be kept in
+ /// sync.
+ void applyMapping(const OperandsMapper &OpdMapper) const {
+ // The only mapping we know how to handle is the default mapping.
+ if (OpdMapper.getInstrMapping().getID() == DefaultMappingID)
+ return applyDefaultMapping(OpdMapper);
+ // For other mapping, the target needs to do the right thing.
+ // If that means calling applyDefaultMapping, fine, but this
+ // must be explicitly stated.
+ applyMappingImpl(OpdMapper);
+ }
+
+ /// Get the size in bits of \p Reg.
+ /// Utility method to get the size of any registers. Unlike
+ /// MachineRegisterInfo::getSize, the register does not need to be a
+ /// virtual register.
+ ///
+ /// \pre \p Reg != 0 (NoRegister).
+ static unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI,
+ const TargetRegisterInfo &TRI);
+
+ /// Check that information hold by this instance make sense for the
+ /// given \p TRI.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(const TargetRegisterInfo &TRI) const;
+};
+
+inline raw_ostream &
+operator<<(raw_ostream &OS,
+ const RegisterBankInfo::PartialMapping &PartMapping) {
+ PartMapping.print(OS);
+ return OS;
+}
+
+inline raw_ostream &
+operator<<(raw_ostream &OS, const RegisterBankInfo::ValueMapping &ValMapping) {
+ ValMapping.print(OS);
+ return OS;
+}
+
+inline raw_ostream &
+operator<<(raw_ostream &OS,
+ const RegisterBankInfo::InstructionMapping &InstrMapping) {
+ InstrMapping.print(OS);
+ return OS;
+}
+
+inline raw_ostream &
+operator<<(raw_ostream &OS, const RegisterBankInfo::OperandsMapper &OpdMapper) {
+ OpdMapper.print(OS, /*ForDebug*/ false);
+ return OS;
+}
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/Types.h b/include/llvm/CodeGen/GlobalISel/Types.h
new file mode 100644
index 0000000000000..7d974878d3b9f
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/Types.h
@@ -0,0 +1,32 @@
+//===-- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes high level types that are used by several passes or
+/// APIs involved in the GlobalISel pipeline.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_TYPES_H
+#define LLVM_CODEGEN_GLOBALISEL_TYPES_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/Value.h"
+
+namespace llvm {
+
+/// Map a value to a virtual register.
+/// For now, we chose to map aggregate types to on single virtual
+/// register. This might be revisited if it turns out to be inefficient.
+/// PR26161 tracks that.
+/// Note: We need to expose this type to the target hooks for thing like
+/// ABI lowering that would be used during IRTranslation.
+typedef DenseMap<const Value *, unsigned> ValueToVReg;
+
+} // End namespace llvm.
+#endif
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 158ff3cd36a83..89cb7a86f99f6 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -257,6 +257,9 @@ namespace ISD {
/// value as an integer 0/1 value.
FGETSIGN,
+ /// Returns platform specific canonical encoding of a floating point number.
+ FCANONICALIZE,
+
/// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the
/// specified, possibly variable, elements. The number of elements is
/// required to be a power of two. The types of the operands must all be
@@ -483,6 +486,12 @@ namespace ISD {
/// the same bit size (e.g. f32 <-> i32). This can also be used for
/// int-to-int or fp-to-fp conversions, but that is a noop, deleted by
/// getNode().
+ ///
+ /// This operator is subtly different from the bitcast instruction from
+ /// LLVM-IR since this node may change the bits in the register. For
+ /// example, this occurs on big-endian NEON and big-endian MSA where the
+ /// layout of the bits in the register depends on the vector type and this
+ /// operator acts as a shuffle operation for some vector type combinations.
BITCAST,
/// ADDRSPACECAST - This operator converts between pointers of different
@@ -869,56 +878,52 @@ namespace ISD {
SETCC_INVALID // Marker value.
};
- /// isSignedIntSetCC - Return true if this is a setcc instruction that
- /// performs a signed comparison when used with integer operands.
+ /// Return true if this is a setcc instruction that performs a signed
+ /// comparison when used with integer operands.
inline bool isSignedIntSetCC(CondCode Code) {
return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE;
}
- /// isUnsignedIntSetCC - Return true if this is a setcc instruction that
- /// performs an unsigned comparison when used with integer operands.
+ /// Return true if this is a setcc instruction that performs an unsigned
+ /// comparison when used with integer operands.
inline bool isUnsignedIntSetCC(CondCode Code) {
return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE;
}
- /// isTrueWhenEqual - Return true if the specified condition returns true if
- /// the two operands to the condition are equal. Note that if one of the two
- /// operands is a NaN, this value is meaningless.
+ /// Return true if the specified condition returns true if the two operands to
+ /// the condition are equal. Note that if one of the two operands is a NaN,
+ /// this value is meaningless.
inline bool isTrueWhenEqual(CondCode Cond) {
return ((int)Cond & 1) != 0;
}
- /// getUnorderedFlavor - This function returns 0 if the condition is always
- /// false if an operand is a NaN, 1 if the condition is always true if the
- /// operand is a NaN, and 2 if the condition is undefined if the operand is a
- /// NaN.
+ /// This function returns 0 if the condition is always false if an operand is
+ /// a NaN, 1 if the condition is always true if the operand is a NaN, and 2 if
+ /// the condition is undefined if the operand is a NaN.
inline unsigned getUnorderedFlavor(CondCode Cond) {
return ((int)Cond >> 3) & 3;
}
- /// getSetCCInverse - Return the operation corresponding to !(X op Y), where
- /// 'op' is a valid SetCC operation.
+ /// Return the operation corresponding to !(X op Y), where 'op' is a valid
+ /// SetCC operation.
CondCode getSetCCInverse(CondCode Operation, bool isInteger);
- /// getSetCCSwappedOperands - Return the operation corresponding to (Y op X)
- /// when given the operation for (X op Y).
+ /// Return the operation corresponding to (Y op X) when given the operation
+ /// for (X op Y).
CondCode getSetCCSwappedOperands(CondCode Operation);
- /// getSetCCOrOperation - Return the result of a logical OR between different
- /// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This
- /// function returns SETCC_INVALID if it is not possible to represent the
- /// resultant comparison.
+ /// Return the result of a logical OR between different comparisons of
+ /// identical values: ((X op1 Y) | (X op2 Y)). This function returns
+ /// SETCC_INVALID if it is not possible to represent the resultant comparison.
CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, bool isInteger);
- /// getSetCCAndOperation - Return the result of a logical AND between
- /// different comparisons of identical values: ((X op1 Y) & (X op2 Y)). This
- /// function returns SETCC_INVALID if it is not possible to represent the
- /// resultant comparison.
+ /// Return the result of a logical AND between different comparisons of
+ /// identical values: ((X op1 Y) & (X op2 Y)). This function returns
+ /// SETCC_INVALID if it is not possible to represent the resultant comparison.
CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger);
//===--------------------------------------------------------------------===//
- /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT
- /// supports.
+ /// This enum defines the various converts CONVERT_RNDSAT supports.
enum CvtCode {
CVT_FF, /// Float from Float
CVT_FS, /// Float from Signed
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index f1ea2c03f13cc..04e840dea2caa 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -190,8 +190,8 @@ namespace llvm {
void dump() const;
};
- typedef SmallVector<Segment,4> Segments;
- typedef SmallVector<VNInfo*,4> VNInfoList;
+ typedef SmallVector<Segment, 2> Segments;
+ typedef SmallVector<VNInfo *, 2> VNInfoList;
Segments segments; // the liveness segments
VNInfoList valnos; // value#'s
@@ -613,6 +613,9 @@ namespace llvm {
BumpPtrAllocator &Allocator)
: LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) {
}
+
+ void print(raw_ostream &OS) const;
+ void dump() const;
};
private:
@@ -712,10 +715,6 @@ namespace llvm {
/// are not considered valid and should only exist temporarily).
void removeEmptySubRanges();
- /// Construct main live range by merging the SubRanges of @p LI.
- void constructMainRangeFromSubranges(const SlotIndexes &Indexes,
- VNInfo::Allocator &VNIAllocator);
-
/// getSize - Returns the sum of sizes of all the LiveRange's.
///
unsigned getSize() const;
@@ -759,6 +758,12 @@ namespace llvm {
void freeSubRange(SubRange *S);
};
+ inline raw_ostream &operator<<(raw_ostream &OS,
+ const LiveInterval::SubRange &SR) {
+ SR.print(OS);
+ return OS;
+ }
+
inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) {
LI.print(OS);
return OS;
@@ -868,6 +873,5 @@ namespace llvm {
void Distribute(LiveInterval &LI, LiveInterval *LIV[],
MachineRegisterInfo &MRI);
};
-
}
#endif
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 87421e2f83b4a..d4ee0582cc412 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -31,7 +31,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <cmath>
-#include <iterator>
namespace llvm {
@@ -105,7 +104,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
const MachineBlockFrequencyInfo *MBFI,
- const MachineInstr *Instr);
+ const MachineInstr &Instr);
LiveInterval &getInterval(unsigned Reg) {
if (hasInterval(Reg))
@@ -145,7 +144,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Given a register and an instruction, adds a live segment from that
/// instruction to the end of its MBB.
LiveInterval::Segment addSegmentToEndOfBlock(unsigned reg,
- MachineInstr* startInst);
+ MachineInstr &startInst);
/// After removing some uses of a register, shrink its live range to just
/// the remaining uses. This method does not compute reaching defs for new
@@ -195,13 +194,13 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// isNotInMIMap - returns true if the specified machine instr has been
/// removed or was never entered in the map.
- bool isNotInMIMap(const MachineInstr* Instr) const {
+ bool isNotInMIMap(const MachineInstr &Instr) const {
return !Indexes->hasIndex(Instr);
}
/// Returns the base index of the given instruction.
- SlotIndex getInstructionIndex(const MachineInstr *instr) const {
- return Indexes->getInstructionIndex(instr);
+ SlotIndex getInstructionIndex(const MachineInstr &Instr) const {
+ return Indexes->getInstructionIndex(Instr);
}
/// Returns the instruction associated with the given index.
@@ -240,21 +239,21 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
RegMaskBlocks.push_back(std::make_pair(RegMaskSlots.size(), 0));
}
- SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) {
+ SlotIndex InsertMachineInstrInMaps(MachineInstr &MI) {
return Indexes->insertMachineInstrInMaps(MI);
}
void InsertMachineInstrRangeInMaps(MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E) {
for (MachineBasicBlock::iterator I = B; I != E; ++I)
- Indexes->insertMachineInstrInMaps(I);
+ Indexes->insertMachineInstrInMaps(*I);
}
- void RemoveMachineInstrFromMaps(MachineInstr *MI) {
+ void RemoveMachineInstrFromMaps(MachineInstr &MI) {
Indexes->removeMachineInstrFromMaps(MI);
}
- void ReplaceMachineInstrInMaps(MachineInstr *MI, MachineInstr *NewMI) {
+ void ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI) {
Indexes->replaceMachineInstrInMaps(MI, NewMI);
}
@@ -288,7 +287,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// are not supported.
///
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
- void handleMove(MachineInstr* MI, bool UpdateFlags = false);
+ void handleMove(MachineInstr &MI, bool UpdateFlags = false);
/// moveIntoBundle - Update intervals for operands of MI so that they
/// begin/end on the SlotIndex for BundleStart.
@@ -298,7 +297,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Requires MI and BundleStart to have SlotIndexes, and assumes
/// existing liveness is accurate. BundleStart should be the first
/// instruction in the Bundle.
- void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart,
+ void handleMoveIntoBundle(MachineInstr &MI, MachineInstr &BundleStart,
bool UpdateFlags = false);
/// repairIntervalsInRange - Update live intervals for instructions in a
@@ -406,6 +405,11 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void splitSeparateComponents(LiveInterval &LI,
SmallVectorImpl<LiveInterval*> &SplitLIs);
+ /// For live interval \p LI with correct SubRanges construct matching
+ /// information for the main live range. Expects the main live range to not
+ /// have any segments or value numbers.
+ void constructMainRangeFromSubranges(LiveInterval &LI);
+
private:
/// Compute live intervals for all virtual registers.
void computeVirtRegs();
diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h
index 3bdf5ae8d0132..1cea9d5b90d64 100644
--- a/include/llvm/CodeGen/LivePhysRegs.h
+++ b/include/llvm/CodeGen/LivePhysRegs.h
@@ -84,12 +84,8 @@ public:
void removeReg(unsigned Reg) {
assert(TRI && "LivePhysRegs is not initialized.");
assert(Reg <= TRI->getNumRegs() && "Expected a physical register.");
- for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
- SubRegs.isValid(); ++SubRegs)
- LiveRegs.erase(*SubRegs);
- for (MCSuperRegIterator SuperRegs(Reg, TRI, /*IncludeSelf=*/false);
- SuperRegs.isValid(); ++SuperRegs)
- LiveRegs.erase(*SuperRegs);
+ for (MCRegAliasIterator R(Reg, TRI, true); R.isValid(); ++R)
+ LiveRegs.erase(*R);
}
/// \brief Removes physical registers clobbered by the regmask operand @p MO.
@@ -97,10 +93,15 @@ public:
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers);
/// \brief Returns true if register @p Reg is contained in the set. This also
- /// works if only the super register of @p Reg has been defined, because we
- /// always add also all sub-registers to the set.
+ /// works if only the super register of @p Reg has been defined, because
+ /// addReg() always adds all sub-registers to the set as well.
+ /// Note: Returns false if just some sub registers are live, use available()
+ /// when searching a free register.
bool contains(unsigned Reg) const { return LiveRegs.count(Reg); }
+ /// Returns true if register \p Reg and no aliasing register is in the set.
+ bool available(const MachineRegisterInfo &MRI, unsigned Reg) const;
+
/// \brief Simulates liveness when stepping backwards over an
/// instruction(bundle): Remove Defs, add uses. This is the recommended way of
/// calculating liveness.
@@ -116,15 +117,20 @@ public:
void stepForward(const MachineInstr &MI,
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> &Clobbers);
- /// \brief Adds all live-in registers of basic block @p MBB; After prologue/
- /// epilogue insertion \p AddPristines should be set to true to insert the
+ /// Adds all live-in registers of basic block @p MBB.
+ /// Live in registers are the registers in the blocks live-in list and the
/// pristine registers.
- void addLiveIns(const MachineBasicBlock *MBB, bool AddPristines = false);
+ void addLiveIns(const MachineBasicBlock &MBB);
+
+ /// Adds all live-out registers of basic 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);
- /// \brief Adds all live-out registers of basic block @p MBB; After prologue/
- /// epilogue insertion \p AddPristinesAndCSRs should be set to true.
- void addLiveOuts(const MachineBasicBlock *MBB,
- bool AddPristinesAndCSRs = false);
+ /// Like addLiveOuts() but does not add pristine registers/callee saved
+ /// registers.
+ void addLiveOutsNoPristines(const MachineBasicBlock &MBB);
typedef SparseSet<unsigned>::const_iterator const_iterator;
const_iterator begin() const { return LiveRegs.begin(); }
diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h
index 2271e3352aa27..4250777682ba5 100644
--- a/include/llvm/CodeGen/LiveRangeEdit.h
+++ b/include/llvm/CodeGen/LiveRangeEdit.h
@@ -72,6 +72,10 @@ private:
/// ScannedRemattable - true when remattable values have been identified.
bool ScannedRemattable;
+ /// DeadRemats - The saved instructions which have already been dead after
+ /// rematerialization but not deleted yet -- to be done in postOptimization.
+ SmallPtrSet<MachineInstr *, 32> *DeadRemats;
+
/// Remattable - Values defined by remattable instructions as identified by
/// tii.isTriviallyReMaterializable().
SmallPtrSet<const VNInfo*,4> Remattable;
@@ -96,7 +100,8 @@ private:
SmallVector<LiveInterval*, 8>,
SmallPtrSet<LiveInterval*, 8> > ToShrinkSet;
/// Helper for eliminateDeadDefs.
- void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink);
+ void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink,
+ AliasAnalysis *AA);
/// MachineRegisterInfo callback to notify when new virtual
/// registers are created.
@@ -116,13 +121,16 @@ public:
/// @param vrm Map of virtual registers to physical registers for this
/// function. If NULL, no virtual register map updates will
/// be done. This could be the case if called before Regalloc.
+ /// @param deadRemats The collection of all the instructions defining an
+ /// original reg and are dead after remat.
LiveRangeEdit(LiveInterval *parent, SmallVectorImpl<unsigned> &newRegs,
MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm,
- Delegate *delegate = nullptr)
+ Delegate *delegate = nullptr,
+ SmallPtrSet<MachineInstr *, 32> *deadRemats = nullptr)
: Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis),
- VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()),
- TheDelegate(delegate), FirstNew(newRegs.size()),
- ScannedRemattable(false) {
+ VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()), TheDelegate(delegate),
+ FirstNew(newRegs.size()), ScannedRemattable(false),
+ DeadRemats(deadRemats) {
MRI.setDelegate(this);
}
@@ -142,6 +150,16 @@ public:
bool empty() const { return size() == 0; }
unsigned get(unsigned idx) const { return NewRegs[idx+FirstNew]; }
+ /// pop_back - It allows LiveRangeEdit users to drop new registers.
+ /// The context is when an original def instruction of a register is
+ /// dead after rematerialization, we still want to keep it for following
+ /// rematerializations. We save the def instruction in DeadRemats,
+ /// and replace the original dst register with a new dummy register so
+ /// the live range of original dst register can be shrinked normally.
+ /// We don't want to allocate phys register for the dummy register, so
+ /// we want to drop it from the NewRegs set.
+ void pop_back() { NewRegs.pop_back(); }
+
ArrayRef<unsigned> regs() const {
return makeArrayRef(NewRegs).slice(FirstNew);
}
@@ -175,15 +193,15 @@ public:
/// Remat - Information needed to rematerialize at a specific location.
struct Remat {
VNInfo *ParentVNI; // parent_'s value at the remat location.
- MachineInstr *OrigMI; // Instruction defining ParentVNI.
+ MachineInstr *OrigMI; // Instruction defining OrigVNI. It contains the
+ // real expr for remat.
explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI), OrigMI(nullptr) {}
};
/// canRematerializeAt - Determine if ParentVNI can be rematerialized at
/// UseIdx. It is assumed that parent_.getVNINfoAt(UseIdx) == ParentVNI.
/// When cheapAsAMove is set, only cheap remats are allowed.
- bool canRematerializeAt(Remat &RM,
- SlotIndex UseIdx,
+ bool canRematerializeAt(Remat &RM, VNInfo *OrigVNI, SlotIndex UseIdx,
bool cheapAsAMove);
/// rematerializeAt - Rematerialize RM.ParentVNI into DestReg by inserting an
@@ -208,6 +226,12 @@ public:
return Rematted.count(ParentVNI);
}
+ void markDeadRemat(MachineInstr *inst) {
+ // DeadRemats is an optional field.
+ if (DeadRemats)
+ DeadRemats->insert(inst);
+ }
+
/// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try
/// to erase it from LIS.
void eraseVirtReg(unsigned Reg);
@@ -218,8 +242,9 @@ public:
/// RegsBeingSpilled lists registers currently being spilled by the register
/// allocator. These registers should not be split into new intervals
/// as currently those new intervals are not guaranteed to spill.
- void eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
- ArrayRef<unsigned> RegsBeingSpilled = None);
+ void eliminateDeadDefs(SmallVectorImpl<MachineInstr *> &Dead,
+ ArrayRef<unsigned> RegsBeingSpilled = None,
+ AliasAnalysis *AA = nullptr);
/// calculateRegClassAndHint - Recompute register class and hint for each new
/// register.
diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h
index 55b97dc3e71d9..bc210dda08c09 100644
--- a/include/llvm/CodeGen/LiveVariables.h
+++ b/include/llvm/CodeGen/LiveVariables.h
@@ -91,9 +91,9 @@ public:
/// removeKill - Delete a kill corresponding to the specified
/// machine instruction. Returns true if there was a kill
/// corresponding to this instruction, false otherwise.
- bool removeKill(MachineInstr *MI) {
- std::vector<MachineInstr*>::iterator
- I = std::find(Kills.begin(), Kills.end(), MI);
+ bool removeKill(MachineInstr &MI) {
+ std::vector<MachineInstr *>::iterator I =
+ std::find(Kills.begin(), Kills.end(), &MI);
if (I == Kills.end())
return false;
Kills.erase(I);
@@ -155,10 +155,10 @@ private: // Intermediate data structures
/// HandleRegMask - Call HandlePhysRegKill for all registers clobbered by Mask.
void HandleRegMask(const MachineOperand&);
- void HandlePhysRegUse(unsigned Reg, MachineInstr *MI);
+ void HandlePhysRegUse(unsigned Reg, MachineInstr &MI);
void HandlePhysRegDef(unsigned Reg, MachineInstr *MI,
SmallVectorImpl<unsigned> &Defs);
- void UpdatePhysRegDefs(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs);
+ void UpdatePhysRegDefs(MachineInstr &MI, SmallVectorImpl<unsigned> &Defs);
/// FindLastRefOrPartRef - Return the last reference or partial reference of
/// the specified register.
@@ -176,7 +176,7 @@ private: // Intermediate data structures
/// is coming from.
void analyzePHINodes(const MachineFunction& Fn);
- void runOnInstr(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs);
+ void runOnInstr(MachineInstr &MI, SmallVectorImpl<unsigned> &Defs);
void runOnBlock(MachineBasicBlock *MBB, unsigned NumRegs);
public:
@@ -185,37 +185,37 @@ public:
/// RegisterDefIsDead - Return true if the specified instruction defines the
/// specified register, but that definition is dead.
- bool RegisterDefIsDead(MachineInstr *MI, unsigned Reg) const;
+ bool RegisterDefIsDead(MachineInstr &MI, unsigned Reg) const;
//===--------------------------------------------------------------------===//
// API to update live variable information
/// replaceKillInstruction - Update register kill info by replacing a kill
/// instruction with a new one.
- void replaceKillInstruction(unsigned Reg, MachineInstr *OldMI,
- MachineInstr *NewMI);
+ void replaceKillInstruction(unsigned Reg, MachineInstr &OldMI,
+ MachineInstr &NewMI);
/// addVirtualRegisterKilled - Add information about the fact that the
/// specified register is killed after being used by the specified
/// instruction. If AddIfNotFound is true, add a implicit operand if it's
/// not found.
- void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI,
+ void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr &MI,
bool AddIfNotFound = false) {
- if (MI->addRegisterKilled(IncomingReg, TRI, AddIfNotFound))
- getVarInfo(IncomingReg).Kills.push_back(MI);
+ if (MI.addRegisterKilled(IncomingReg, TRI, AddIfNotFound))
+ getVarInfo(IncomingReg).Kills.push_back(&MI);
}
/// removeVirtualRegisterKilled - Remove the specified kill of the virtual
/// register from the live variable information. Returns true if the
/// variable was marked as killed by the specified instruction,
/// false otherwise.
- bool removeVirtualRegisterKilled(unsigned reg, MachineInstr *MI) {
+ bool removeVirtualRegisterKilled(unsigned reg, MachineInstr &MI) {
if (!getVarInfo(reg).removeKill(MI))
return false;
bool Removed = false;
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI->getOperand(i);
+ for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI.getOperand(i);
if (MO.isReg() && MO.isKill() && MO.getReg() == reg) {
MO.setIsKill(false);
Removed = true;
@@ -230,28 +230,28 @@ public:
/// removeVirtualRegistersKilled - Remove all killed info for the specified
/// instruction.
- void removeVirtualRegistersKilled(MachineInstr *MI);
+ void removeVirtualRegistersKilled(MachineInstr &MI);
/// addVirtualRegisterDead - Add information about the fact that the specified
/// register is dead after being used by the specified instruction. If
/// AddIfNotFound is true, add a implicit operand if it's not found.
- void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI,
+ void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr &MI,
bool AddIfNotFound = false) {
- if (MI->addRegisterDead(IncomingReg, TRI, AddIfNotFound))
- getVarInfo(IncomingReg).Kills.push_back(MI);
+ if (MI.addRegisterDead(IncomingReg, TRI, AddIfNotFound))
+ getVarInfo(IncomingReg).Kills.push_back(&MI);
}
/// removeVirtualRegisterDead - Remove the specified kill of the virtual
/// register from the live variable information. Returns true if the
/// variable was marked dead at the specified instruction, false
/// otherwise.
- bool removeVirtualRegisterDead(unsigned reg, MachineInstr *MI) {
+ bool removeVirtualRegisterDead(unsigned reg, MachineInstr &MI) {
if (!getVarInfo(reg).removeKill(MI))
return false;
bool Removed = false;
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI->getOperand(i);
+ for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI.getOperand(i);
if (MO.isReg() && MO.isDef() && MO.getReg() == reg) {
MO.setIsDead(false);
Removed = true;
@@ -278,9 +278,8 @@ public:
void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock,
MachineBasicBlock *BB,
std::vector<MachineBasicBlock*> &WorkList);
- void HandleVirtRegDef(unsigned reg, MachineInstr *MI);
- void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB,
- MachineInstr *MI);
+ void HandleVirtRegDef(unsigned reg, MachineInstr &MI);
+ void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, MachineInstr &MI);
bool isLiveIn(unsigned Reg, const MachineBasicBlock &MBB) {
return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI);
diff --git a/include/llvm/CodeGen/MIRParser/MIRParser.h b/include/llvm/CodeGen/MIRParser/MIRParser.h
index a569d5ec1f5e8..dd0780397f429 100644
--- a/include/llvm/CodeGen/MIRParser/MIRParser.h
+++ b/include/llvm/CodeGen/MIRParser/MIRParser.h
@@ -18,7 +18,6 @@
#ifndef LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
#define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineFunctionInitializer.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -26,6 +25,7 @@
namespace llvm {
+class StringRef;
class MIRParserImpl;
class SMDiagnostic;
diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h
index 14d3744741c5c..7f9c448333362 100644
--- a/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/include/llvm/CodeGen/MIRYamlMapping.h
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
//
-// The MIR serialization library is currently a work in progress. It can't
-// serialize machine functions at this time.
-//
// This file implements the mapping between various MIR data structures and
// their corresponding YAML representation.
//
@@ -385,6 +382,8 @@ struct MachineFunction {
unsigned Alignment = 0;
bool ExposesReturnsTwice = false;
bool HasInlineAsm = false;
+ // MachineFunctionProperties
+ bool AllVRegsAllocated = false;
// Register information
bool IsSSA = false;
bool TracksRegLiveness = false;
@@ -408,6 +407,7 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapOptional("alignment", MF.Alignment);
YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
+ YamlIO.mapOptional("allVRegsAllocated", MF.AllVRegsAllocated);
YamlIO.mapOptional("isSSA", MF.IsSSA);
YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 3d58c499823e8..d5f918eb2bb90 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -15,6 +15,8 @@
#define LLVM_CODEGEN_MACHINEBASICBLOCK_H
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/CodeGen/MachineInstrBundleIterator.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -157,80 +159,14 @@ public:
const MachineFunction *getParent() const { return xParent; }
MachineFunction *getParent() { return xParent; }
- /// MachineBasicBlock iterator that automatically skips over MIs that are
- /// inside bundles (i.e. walk top level MIs only).
- template<typename Ty, typename IterTy>
- class bundle_iterator
- : public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
- IterTy MII;
-
- public:
- bundle_iterator(IterTy MI) : MII(MI) {}
-
- bundle_iterator(Ty &MI) : MII(MI) {
- assert(!MI.isBundledWithPred() &&
- "It's not legal to initialize bundle_iterator with a bundled MI");
- }
- bundle_iterator(Ty *MI) : MII(MI) {
- assert((!MI || !MI->isBundledWithPred()) &&
- "It's not legal to initialize bundle_iterator with a bundled MI");
- }
- // Template allows conversion from const to nonconst.
- template<class OtherTy, class OtherIterTy>
- bundle_iterator(const bundle_iterator<OtherTy, OtherIterTy> &I)
- : MII(I.getInstrIterator()) {}
- bundle_iterator() : MII(nullptr) {}
-
- Ty &operator*() const { return *MII; }
- Ty *operator->() const { return &operator*(); }
-
- operator Ty *() const { return MII.getNodePtrUnchecked(); }
-
- bool operator==(const bundle_iterator &X) const {
- return MII == X.MII;
- }
- bool operator!=(const bundle_iterator &X) const {
- return !operator==(X);
- }
-
- // Increment and decrement operators...
- bundle_iterator &operator--() { // predecrement - Back up
- do --MII;
- while (MII->isBundledWithPred());
- return *this;
- }
- bundle_iterator &operator++() { // preincrement - Advance
- while (MII->isBundledWithSucc())
- ++MII;
- ++MII;
- return *this;
- }
- bundle_iterator operator--(int) { // postdecrement operators...
- bundle_iterator tmp = *this;
- --*this;
- return tmp;
- }
- bundle_iterator operator++(int) { // postincrement operators...
- bundle_iterator tmp = *this;
- ++*this;
- return tmp;
- }
-
- IterTy getInstrIterator() const {
- return MII;
- }
- };
-
typedef Instructions::iterator instr_iterator;
typedef Instructions::const_iterator const_instr_iterator;
typedef std::reverse_iterator<instr_iterator> reverse_instr_iterator;
typedef
std::reverse_iterator<const_instr_iterator> const_reverse_instr_iterator;
- typedef
- bundle_iterator<MachineInstr,instr_iterator> iterator;
- typedef
- bundle_iterator<const MachineInstr,const_instr_iterator> const_iterator;
+ typedef MachineInstrBundleIterator<MachineInstr> iterator;
+ typedef MachineInstrBundleIterator<const MachineInstr> const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
@@ -257,6 +193,13 @@ public:
reverse_instr_iterator instr_rend () { return Insts.rend(); }
const_reverse_instr_iterator instr_rend () const { return Insts.rend(); }
+ typedef iterator_range<instr_iterator> instr_range;
+ typedef iterator_range<const_instr_iterator> const_instr_range;
+ instr_range instrs() { return instr_range(instr_begin(), instr_end()); }
+ const_instr_range instrs() const {
+ return const_instr_range(instr_begin(), instr_end());
+ }
+
iterator begin() { return instr_begin(); }
const_iterator begin() const { return instr_begin(); }
iterator end () { return instr_end(); }
@@ -399,10 +342,6 @@ public:
/// via an exception handler.
void setIsEHPad(bool V = true) { IsEHPad = V; }
- /// If this block has a successor that is a landing pad, return it. Otherwise
- /// return NULL.
- const MachineBasicBlock *getLandingPadSuccessor() const;
-
bool hasEHPadSuccessor() const;
/// Returns true if this is the entry block of an EH funclet.
@@ -563,7 +502,13 @@ public:
///
/// This function updates LiveVariables, MachineDominatorTree, and
/// MachineLoopInfo, as applicable.
- MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P);
+ MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P);
+
+ /// Check if the edge between this block and the given successor \p
+ /// Succ, can be split. If this returns true a subsequent call to
+ /// SplitCriticalEdge is guaranteed to return a valid basic block if
+ /// no changes occured in the meantime.
+ bool canSplitCriticalEdge(const MachineBasicBlock *Succ) const;
void pop_front() { Insts.pop_front(); }
void pop_back() { Insts.pop_back(); }
@@ -729,9 +674,9 @@ public:
// Debugging methods.
void dump() const;
- void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
+ void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
void print(raw_ostream &OS, ModuleSlotTracker &MST,
- SlotIndexes * = nullptr) const;
+ const SlotIndexes* = nullptr) const;
// Printing method used by LoopInfo.
void printAsOperand(raw_ostream &OS, bool PrintType = true) const;
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index feb394e7a69e0..7a236086ed09c 100644
--- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
+#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/BlockFrequency.h"
#include <climits>
@@ -50,7 +51,10 @@ public:
///
BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const;
+ Optional<uint64_t> getBlockProfileCount(const MachineBasicBlock *MBB) const;
+
const MachineFunction *getFunction() const;
+ const MachineBranchProbabilityInfo *getMBPI() const;
void view() const;
// Print the block frequency Freq to OS using the current functions entry
diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h
index f3891227746fe..11238016d447b 100644
--- a/include/llvm/CodeGen/MachineCombinerPattern.h
+++ b/include/llvm/CodeGen/MachineCombinerPattern.h
@@ -38,7 +38,40 @@ enum class MachineCombinerPattern {
MULSUBX_OP1,
MULSUBX_OP2,
MULADDXI_OP1,
- MULSUBXI_OP1
+ MULSUBXI_OP1,
+ // Floating Point
+ FMULADDS_OP1,
+ FMULADDS_OP2,
+ FMULSUBS_OP1,
+ FMULSUBS_OP2,
+ FMULADDD_OP1,
+ FMULADDD_OP2,
+ FMULSUBD_OP1,
+ FMULSUBD_OP2,
+ FMLAv1i32_indexed_OP1,
+ FMLAv1i32_indexed_OP2,
+ FMLAv1i64_indexed_OP1,
+ FMLAv1i64_indexed_OP2,
+ FMLAv2f32_OP2,
+ FMLAv2f32_OP1,
+ FMLAv2f64_OP1,
+ FMLAv2f64_OP2,
+ FMLAv2i32_indexed_OP1,
+ FMLAv2i32_indexed_OP2,
+ FMLAv2i64_indexed_OP1,
+ FMLAv2i64_indexed_OP2,
+ FMLAv4f32_OP1,
+ FMLAv4f32_OP2,
+ FMLAv4i32_indexed_OP1,
+ FMLAv4i32_indexed_OP2,
+ FMLSv1i32_indexed_OP2,
+ FMLSv1i64_indexed_OP2,
+ FMLSv2i32_indexed_OP2,
+ FMLSv2i64_indexed_OP2,
+ FMLSv2f32_OP2,
+ FMLSv2f64_OP2,
+ FMLSv4i32_indexed_OP2,
+ FMLSv4f32_OP2
};
} // end namespace llvm
diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h
index a69936f6e267c..ed7cc277e8b6a 100644
--- a/include/llvm/CodeGen/MachineDominators.h
+++ b/include/llvm/CodeGen/MachineDominators.h
@@ -216,6 +216,8 @@ public:
void releaseMemory() override;
+ void verifyAnalysis() const override;
+
void print(raw_ostream &OS, const Module*) const override;
/// \brief Record that the critical edge (FromBB, ToBB) has been
@@ -239,6 +241,27 @@ public:
"A basic block inserted via edge splitting cannot appear twice");
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
+ /// verification fails.
+ void verifyDomTree() const;
};
//===-------------------------------------
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index e50779aacc23e..59755674c69e5 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -122,21 +122,28 @@ class MachineFrameInfo {
// arguments have ABI-prescribed offsets).
bool isAliased;
+ /// If true, the object has been zero-extended.
+ bool isZExt;
+
+ /// If true, the object has been zero-extended.
+ bool isSExt;
+
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM,
bool isSS, const AllocaInst *Val, bool A)
: SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM),
isSpillSlot(isSS), isStatepointSpillSlot(false), Alloca(Val),
- PreAllocated(false), isAliased(A) {}
+ PreAllocated(false), isAliased(A), isZExt(false), isSExt(false) {}
};
/// The alignment of the stack.
unsigned StackAlignment;
- /// Can the stack be realigned.
- /// Targets that set this to false don't have the ability to overalign
- /// their stack frame, and thus, overaligned allocas are all treated
- /// as dynamic allocations and the target must handle them as part
- /// of DYNAMIC_STACKALLOC lowering.
+ /// Can the stack be realigned. This can be false if the target does not
+ /// support stack realignment, or if the user asks us not to realign the
+ /// stack. In this situation, overaligned allocas are all treated as dynamic
+ /// allocations and the target must handle them as part of DYNAMIC_STACKALLOC
+ /// lowering. All non-alloca stack objects have their alignment clamped to the
+ /// base ABI stack alignment.
/// FIXME: There is room for improvement in this case, in terms of
/// grouping overaligned allocas into a "secondary stack frame" and
/// then only use a single alloca to allocate this frame and only a
@@ -145,39 +152,42 @@ class MachineFrameInfo {
/// realignment.
bool StackRealignable;
+ /// Whether the function has the \c alignstack attribute.
+ bool ForcedRealign;
+
/// The list of stack objects allocated.
std::vector<StackObject> Objects;
/// This contains the number of fixed objects contained on
/// the stack. Because fixed objects are stored at a negative index in the
/// Objects list, this is also the index to the 0th object in the list.
- unsigned NumFixedObjects;
+ unsigned NumFixedObjects = 0;
/// This boolean keeps track of whether any variable
/// sized objects have been allocated yet.
- bool HasVarSizedObjects;
+ bool HasVarSizedObjects = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.frameaddress.
- bool FrameAddressTaken;
+ bool FrameAddressTaken = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.returnaddress.
- bool ReturnAddressTaken;
+ bool ReturnAddressTaken = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.experimental.stackmap.
- bool HasStackMap;
+ bool HasStackMap = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.experimental.patchpoint.
- bool HasPatchPoint;
+ bool HasPatchPoint = false;
/// The prolog/epilog code inserter calculates the final stack
/// offsets for all of the fixed size objects, updating the Objects list
/// above. It then updates StackSize to contain the number of bytes that need
/// to be allocated on entry to the function.
- uint64_t StackSize;
+ uint64_t StackSize = 0;
/// The amount that a frame offset needs to be adjusted to
/// have the actual offset from the stack/frame pointer. The exact usage of
@@ -188,7 +198,7 @@ class MachineFrameInfo {
/// targets, this value is only used when generating debug info (via
/// TargetRegisterInfo::getFrameIndexReference); when generating code, the
/// corresponding adjustments are performed directly.
- int OffsetAdjustment;
+ int OffsetAdjustment = 0;
/// The prolog/epilog code inserter may process objects that require greater
/// alignment than the default alignment the target provides.
@@ -197,27 +207,27 @@ class MachineFrameInfo {
/// native alignment maintained by the compiler, dynamic alignment code will
/// be needed.
///
- unsigned MaxAlignment;
+ unsigned MaxAlignment = 0;
/// Set to true if this function adjusts the stack -- e.g.,
/// when calling another function. This is only valid during and after
/// prolog/epilog code insertion.
- bool AdjustsStack;
+ bool AdjustsStack = false;
/// Set to true if this function has any function calls.
- bool HasCalls;
+ bool HasCalls = false;
/// The frame index for the stack protector.
- int StackProtectorIdx;
+ int StackProtectorIdx = -1;
/// The frame index for the function context. Used for SjLj exceptions.
- int FunctionContextIdx;
+ int FunctionContextIdx = -1;
/// This contains the size of the largest call frame if the target uses frame
/// setup/destroy pseudo instructions (as defined in the TargetFrameInfo
/// class). This information is important for frame pointer elimination.
/// It is only valid during and after prolog/epilog code insertion.
- unsigned MaxCallFrameSize;
+ unsigned MaxCallFrameSize = 0;
/// The prolog/epilog code inserter fills in this vector with each
/// callee saved register saved in the frame. Beyond its use by the prolog/
@@ -226,79 +236,53 @@ class MachineFrameInfo {
std::vector<CalleeSavedInfo> CSInfo;
/// Has CSInfo been set yet?
- bool CSIValid;
+ bool CSIValid = false;
/// References to frame indices which are mapped
/// into the local frame allocation block. <FrameIdx, LocalOffset>
SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects;
/// Size of the pre-allocated local frame block.
- int64_t LocalFrameSize;
+ int64_t LocalFrameSize = 0;
/// Required alignment of the local object blob, which is the strictest
/// alignment of any object in it.
- unsigned LocalFrameMaxAlign;
+ unsigned LocalFrameMaxAlign = 0;
/// Whether the local object blob needs to be allocated together. If not,
/// PEI should ignore the isPreAllocated flags on the stack objects and
/// just allocate them normally.
- bool UseLocalStackAllocationBlock;
-
- /// Whether the "realign-stack" option is on.
- bool RealignOption;
+ bool UseLocalStackAllocationBlock = false;
/// True if the function dynamically adjusts the stack pointer through some
/// opaque mechanism like inline assembly or Win32 EH.
- bool HasOpaqueSPAdjustment;
+ bool HasOpaqueSPAdjustment = false;
/// True if the function contains operations which will lower down to
/// instructions which manipulate the stack pointer.
- bool HasCopyImplyingStackAdjustment;
+ bool HasCopyImplyingStackAdjustment = false;
/// True if the function contains a call to the llvm.vastart intrinsic.
- bool HasVAStart;
+ bool HasVAStart = false;
/// True if this is a varargs function that contains a musttail call.
- bool HasMustTailInVarArgFunc;
+ bool HasMustTailInVarArgFunc = false;
/// True if this function contains a tail call. If so immutable objects like
/// function arguments are no longer so. A tail call *can* override fixed
/// stack objects like arguments so we can't treat them as immutable.
- bool HasTailCall;
+ bool HasTailCall = false;
/// Not null, if shrink-wrapping found a better place for the prologue.
- MachineBasicBlock *Save;
+ MachineBasicBlock *Save = nullptr;
/// Not null, if shrink-wrapping found a better place for the epilogue.
- MachineBasicBlock *Restore;
+ MachineBasicBlock *Restore = nullptr;
public:
- explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
- bool RealignOpt)
- : StackAlignment(StackAlign), StackRealignable(isStackRealign),
- RealignOption(RealignOpt) {
- StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0;
- HasVarSizedObjects = false;
- FrameAddressTaken = false;
- ReturnAddressTaken = false;
- HasStackMap = false;
- HasPatchPoint = false;
- AdjustsStack = false;
- HasCalls = false;
- StackProtectorIdx = -1;
- FunctionContextIdx = -1;
- MaxCallFrameSize = 0;
- CSIValid = false;
- LocalFrameSize = 0;
- LocalFrameMaxAlign = 0;
- UseLocalStackAllocationBlock = false;
- HasOpaqueSPAdjustment = false;
- HasCopyImplyingStackAdjustment = false;
- HasVAStart = false;
- HasMustTailInVarArgFunc = false;
- Save = nullptr;
- Restore = nullptr;
- HasTailCall = false;
- }
+ explicit MachineFrameInfo(unsigned StackAlignment, bool StackRealignable,
+ bool ForcedRealign)
+ : StackAlignment(StackAlignment), StackRealignable(StackRealignable),
+ ForcedRealign(ForcedRealign) {}
/// Return true if there are any stack objects in this function.
bool hasStackObjects() const { return !Objects.empty(); }
@@ -450,6 +434,30 @@ public:
return Objects[ObjectIdx+NumFixedObjects].SPOffset;
}
+ bool isObjectZExt(int ObjectIdx) const {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ return Objects[ObjectIdx+NumFixedObjects].isZExt;
+ }
+
+ void setObjectZExt(int ObjectIdx, bool IsZExt) {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ Objects[ObjectIdx+NumFixedObjects].isZExt = IsZExt;
+ }
+
+ bool isObjectSExt(int ObjectIdx) const {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ return Objects[ObjectIdx+NumFixedObjects].isSExt;
+ }
+
+ void setObjectSExt(int ObjectIdx, bool IsSExt) {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ Objects[ObjectIdx+NumFixedObjects].isSExt = IsSExt;
+ }
+
/// Set the stack frame offset of the specified object. The
/// offset is relative to the stack pointer on entry to the function.
void setObjectOffset(int ObjectIdx, int64_t SPOffset) {
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index df7c951743c97..4aa9a92e6bee4 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -18,12 +18,15 @@
#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H
#define LLVM_CODEGEN_MACHINEFUNCTION_H
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/ilist.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Recycler.h"
namespace llvm {
@@ -50,6 +53,8 @@ struct ilist_traits<MachineBasicBlock>
: public ilist_default_traits<MachineBasicBlock> {
mutable ilist_half_node<MachineBasicBlock> Sentinel;
public:
+ // FIXME: This downcast is UB. See llvm.org/PR26753.
+ LLVM_NO_SANITIZE("object-size")
MachineBasicBlock *createSentinel() const {
return static_cast<MachineBasicBlock*>(&Sentinel);
}
@@ -85,6 +90,74 @@ struct MachineFunctionInfo {
}
};
+/// Properties which a MachineFunction may have at a given point in time.
+/// Each of these has checking code in the MachineVerifier, and passes can
+/// require that a property be set.
+class MachineFunctionProperties {
+ // TODO: Add MachineVerifier checks for AllVRegsAllocated
+ // TODO: Add a way to print the properties and make more useful error messages
+ // Possible TODO: Allow targets to extend this (perhaps by allowing the
+ // constructor to specify the size of the bit vector)
+ // Possible TODO: Allow requiring the negative (e.g. VRegsAllocated could be
+ // stated as the negative of "has vregs"
+
+public:
+ // The properties are stated in "positive" form; i.e. a pass could require
+ // that the property hold, but not that it does not hold.
+
+ // Property descriptions:
+ // IsSSA: True when the machine function is in SSA form and virtual registers
+ // have a single def.
+ // TracksLiveness: True when tracking register liveness accurately.
+ // While this property is set, register liveness information in basic block
+ // live-in lists and machine instruction operands (e.g. kill flags, implicit
+ // defs) is accurate. This means it can be used to change the code in ways
+ // that affect the values in registers, for example by the register
+ // scavenger.
+ // When this property is clear, liveness is no longer reliable.
+ // AllVRegsAllocated: All virtual registers have been allocated; i.e. all
+ // register operands are physical registers.
+ enum class Property : unsigned {
+ IsSSA,
+ TracksLiveness,
+ AllVRegsAllocated,
+ LastProperty,
+ };
+
+ bool hasProperty(Property P) const {
+ return Properties[static_cast<unsigned>(P)];
+ }
+ MachineFunctionProperties &set(Property P) {
+ Properties.set(static_cast<unsigned>(P));
+ return *this;
+ }
+ MachineFunctionProperties &clear(Property P) {
+ Properties.reset(static_cast<unsigned>(P));
+ return *this;
+ }
+ MachineFunctionProperties &set(const MachineFunctionProperties &MFP) {
+ Properties |= MFP.Properties;
+ return *this;
+ }
+ MachineFunctionProperties &clear(const MachineFunctionProperties &MFP) {
+ Properties.reset(MFP.Properties);
+ return *this;
+ }
+ // Returns true if all properties set in V (i.e. required by a pass) are set
+ // in this.
+ bool verifyRequiredProperties(const MachineFunctionProperties &V) const {
+ return !V.Properties.test(Properties);
+ }
+
+ // Print the MachineFunctionProperties in human-readable form. If OnlySet is
+ // true, only print the properties that are set.
+ void print(raw_ostream &ROS, bool OnlySet=false) const;
+
+private:
+ BitVector Properties =
+ BitVector(static_cast<unsigned>(Property::LastProperty));
+};
+
class MachineFunction {
const Function *Fn;
const TargetMachine &Target;
@@ -146,10 +219,14 @@ class MachineFunction {
/// the attribute itself.
/// This is used to limit optimizations which cannot reason
/// about the control flow of such functions.
- bool ExposesReturnsTwice;
+ bool ExposesReturnsTwice = false;
/// True if the function includes any inline assembly.
- bool HasInlineAsm;
+ bool HasInlineAsm = false;
+
+ /// Current high-level properties of the IR of the function (e.g. is in SSA
+ /// form or whether registers have been allocated)
+ MachineFunctionProperties Properties;
// Allocation management for pseudo source values.
std::unique_ptr<PseudoSourceValueManager> PSVManager;
@@ -268,6 +345,10 @@ public:
HasInlineAsm = B;
}
+ /// Get the function properties
+ const MachineFunctionProperties &getProperties() const { return Properties; }
+ MachineFunctionProperties &getProperties() { return Properties; }
+
/// getInfo - Keep track of various per-function pieces of information for
/// backends that would like to do so.
///
@@ -311,7 +392,7 @@ public:
/// print - Print out the MachineFunction in a format suitable for debugging
/// to the specified stream.
///
- void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
+ void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
/// viewCFG - This function is meant for use from the debugger. You can just
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
@@ -332,9 +413,11 @@ public:
///
void dump() const;
- /// verify - Run the current MachineFunction through the machine code
- /// verifier, useful for debugger use.
- void verify(Pass *p = nullptr, const char *Banner = nullptr) const;
+ /// Run the current MachineFunction through the machine code verifier, useful
+ /// for debugger use.
+ /// \returns true if no problems were found.
+ bool verify(Pass *p = nullptr, const char *Banner = nullptr,
+ bool AbortOnError = true) const;
// Provide accessors for the MachineBasicBlock list...
typedef BasicBlockListType::iterator iterator;
@@ -420,8 +503,7 @@ public:
/// CreateMachineInstr - Allocate a new MachineInstr. Use this instead
/// of `new MachineInstr'.
///
- MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID,
- DebugLoc DL,
+ MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL,
bool NoImp = false);
/// CloneMachineInstr - Create a new MachineInstr which is a copy of the
@@ -449,8 +531,8 @@ public:
/// MachineMemOperands are owned by the MachineFunction and need not be
/// explicitly deallocated.
MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo,
- unsigned f, uint64_t s,
- unsigned base_alignment,
+ MachineMemOperand::Flags f,
+ uint64_t s, unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h
index 50a1f6e96217d..653d1175d04b4 100644
--- a/include/llvm/CodeGen/MachineFunctionPass.h
+++ b/include/llvm/CodeGen/MachineFunctionPass.h
@@ -20,16 +20,24 @@
#define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H
#include "llvm/Pass.h"
+#include "llvm/CodeGen/MachineFunction.h"
namespace llvm {
-class MachineFunction;
-
/// MachineFunctionPass - This class adapts the FunctionPass interface to
/// allow convenient creation of passes that operate on the MachineFunction
/// representation. Instead of overriding runOnFunction, subclasses
/// override runOnMachineFunction.
class MachineFunctionPass : public FunctionPass {
+public:
+ bool doInitialization(Module&) override {
+ // Cache the properties info at module-init time so we don't have to
+ // construct them for every function.
+ RequiredProperties = getRequiredProperties();
+ SetProperties = getSetProperties();
+ ClearedProperties = getClearedProperties();
+ return false;
+ }
protected:
explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {}
@@ -46,7 +54,21 @@ protected:
///
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ virtual MachineFunctionProperties getRequiredProperties() const {
+ return MachineFunctionProperties();
+ }
+ virtual MachineFunctionProperties getSetProperties() const {
+ return MachineFunctionProperties();
+ }
+ virtual MachineFunctionProperties getClearedProperties() const {
+ return MachineFunctionProperties();
+ }
+
private:
+ MachineFunctionProperties RequiredProperties;
+ MachineFunctionProperties SetProperties;
+ MachineFunctionProperties ClearedProperties;
+
/// createPrinterPass - Get a machine function printer pass.
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override;
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index 05c9a9e0b0796..8f1cb9b6f6590 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -16,16 +16,13 @@
#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/MC/MCInstrDesc.h"
@@ -34,10 +31,17 @@
namespace llvm {
+class StringRef;
+template <typename T> class ArrayRef;
template <typename T> class SmallVectorImpl;
+class DILocalVariable;
+class DIExpression;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;
+#ifdef LLVM_BUILD_GLOBAL_ISEL
+class Type;
+#endif
class MachineFunction;
class MachineMemOperand;
@@ -102,6 +106,13 @@ private:
DebugLoc debugLoc; // Source line information.
+#ifdef LLVM_BUILD_GLOBAL_ISEL
+ /// Type of the instruction in case of a generic opcode.
+ /// \invariant This must be nullptr is getOpcode() is not
+ /// in the range of generic opcodes.
+ Type *Ty;
+#endif
+
MachineInstr(const MachineInstr&) = delete;
void operator=(const MachineInstr&) = delete;
// Use MachineFunction::DeleteMachineInstr() instead.
@@ -176,6 +187,11 @@ public:
Flags &= ~((uint8_t)Flag);
}
+ /// Set the type of the instruction.
+ /// \pre getOpcode() is in the range of the generic opcodes.
+ void setType(Type *Ty);
+ Type *getType() const;
+
/// Return true if MI is in a bundle (but not the first MI in a bundle).
///
/// A bundle looks like this before it's finalized:
@@ -248,17 +264,11 @@ public:
/// Return the debug variable referenced by
/// this DBG_VALUE instruction.
- const DILocalVariable *getDebugVariable() const {
- assert(isDebugValue() && "not a DBG_VALUE");
- return cast<DILocalVariable>(getOperand(2).getMetadata());
- }
+ const DILocalVariable *getDebugVariable() const;
/// Return the complex address expression referenced by
/// this DBG_VALUE instruction.
- const DIExpression *getDebugExpression() const {
- assert(isDebugValue() && "not a DBG_VALUE");
- return cast<DIExpression>(getOperand(3).getMetadata());
- }
+ const DIExpression *getDebugExpression() const;
/// Emit an error referring to the source location of this instruction.
/// This should only be used for inline assembly that is somehow
@@ -343,6 +353,14 @@ public:
return make_range(operands_begin() + getDesc().getNumDefs(),
operands_end());
}
+ iterator_range<mop_iterator> explicit_uses() {
+ return make_range(operands_begin() + getDesc().getNumDefs(),
+ operands_begin() + getNumExplicitOperands() );
+ }
+ iterator_range<const_mop_iterator> explicit_uses() const {
+ return make_range(operands_begin() + getDesc().getNumDefs(),
+ operands_begin() + getNumExplicitOperands() );
+ }
/// Returns the number of the operand iterator \p I points to.
unsigned getOperandNo(const_mop_iterator I) const {
@@ -508,6 +526,11 @@ public:
/// Convergent instructions can not be made control-dependent on any
/// additional values.
bool isConvergent(QueryType Type = AnyInBundle) const {
+ if (isInlineAsm()) {
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ if (ExtraInfo & InlineAsm::Extra_IsConvergent)
+ return true;
+ }
return hasProperty(MCID::Convergent, Type);
}
@@ -713,7 +736,7 @@ public:
/// Return true if this instruction is identical to (same
/// opcode and same operands as) the specified instruction.
- bool isIdenticalTo(const MachineInstr *Other,
+ bool isIdenticalTo(const MachineInstr &Other,
MICheckType Check = CheckDefs) const;
/// Unlink 'this' from the containing basic block, and return it without
@@ -899,6 +922,10 @@ public:
return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1;
}
+ /// Returns true if the MachineInstr has an implicit-use operand of exactly
+ /// the given register (not considering sub/super-registers).
+ bool hasRegisterImplicitUseOperand(unsigned Reg) const;
+
/// Returns the operand index that is a use of the specific register or -1
/// if it is not found. It further tightens the search criteria to a use
/// that kills the register if isKill is true.
@@ -1054,8 +1081,8 @@ public:
const TargetRegisterInfo *RegInfo,
bool AddIfNotFound = false);
- /// Clear all kill flags affecting Reg. If RegInfo is
- /// provided, this includes super-register kills.
+ /// Clear all kill flags affecting Reg. If RegInfo is provided, this includes
+ /// all aliasing registers.
void clearRegisterKills(unsigned Reg, const TargetRegisterInfo *RegInfo);
/// We have determined MI defined a register without a use.
@@ -1125,7 +1152,7 @@ public:
/// Copy implicit register operands from specified
/// instruction to this instruction.
- void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI);
+ void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI);
//
// Debugging support
@@ -1168,7 +1195,7 @@ public:
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
}
- /// Erase an operand from an instruction, leaving it with one
+ /// Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
void RemoveOperand(unsigned i);
@@ -1268,7 +1295,7 @@ struct MachineInstrExpressionTrait : DenseMapInfo<MachineInstr*> {
if (RHS == getEmptyKey() || RHS == getTombstoneKey() ||
LHS == getEmptyKey() || LHS == getTombstoneKey())
return LHS == RHS;
- return LHS->isIdenticalTo(RHS, MachineInstr::IgnoreVRegDefs);
+ return LHS->isIdenticalTo(*RHS, MachineInstr::IgnoreVRegDefs);
}
};
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 8fe9b280d5d2d..37b67aa0cf5c0 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -10,7 +10,9 @@
// This file exposes a function named BuildMI, which is useful for dramatically
// simplifying how MachineInstr's are created. It allows use of code like this:
//
-// M = BuildMI(X86::ADDrr8, 2).addReg(argVal1).addReg(argVal2);
+// M = BuildMI(MBB, MI, DL, TII.get(X86::ADD8rr), Dst)
+// .addReg(argVal1)
+// .addReg(argVal2);
//
//===----------------------------------------------------------------------===//
@@ -51,6 +53,8 @@ public:
/// Create a MachineInstrBuilder for manipulating an existing instruction.
/// F must be the machine function that was used to allocate I.
MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {}
+ MachineInstrBuilder(MachineFunction &F, MachineBasicBlock::iterator I)
+ : MF(&F), MI(&*I) {}
/// Allow automatic conversion to the machine instruction we are working on.
operator MachineInstr*() const { return MI; }
@@ -228,25 +232,22 @@ public:
/// Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder &
- copyImplicitOps(const MachineInstr *OtherMI) const {
+ copyImplicitOps(const MachineInstr &OtherMI) const {
MI->copyImplicitOps(*MF, OtherMI);
return *this;
}
};
/// Builder interface. Specify how to create the initial instruction itself.
-inline MachineInstrBuilder BuildMI(MachineFunction &MF,
- DebugLoc DL,
+inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID) {
return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL));
}
/// This version of the builder sets up the first operand as a
/// destination virtual register.
-inline MachineInstrBuilder BuildMI(MachineFunction &MF,
- DebugLoc DL,
- const MCInstrDesc &MCID,
- unsigned DestReg) {
+inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, unsigned DestReg) {
return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL))
.addReg(DestReg, RegState::Define);
}
@@ -256,8 +257,7 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF,
/// operand as a destination virtual register.
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
unsigned DestReg) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -265,10 +265,15 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define);
}
+/// This version of the builder inserts the newly-built instruction before
+/// the given position in the given MachineBasicBlock, and sets up the first
+/// operand as a destination virtual register.
+///
+/// If \c I is inside a bundle, then the newly inserted \a MachineInstr is
+/// added to the same bundle.
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::instr_iterator I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
unsigned DestReg) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -276,18 +281,20 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define);
}
-inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineInstr *I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
unsigned DestReg) {
- if (I->isInsideBundle()) {
- MachineBasicBlock::instr_iterator MII(I);
- return BuildMI(BB, MII, DL, MCID, DestReg);
- }
+ // Calling the overload for instr_iterator is always correct. However, the
+ // definition is not available in headers, so inline the check.
+ if (I.isInsideBundle())
+ return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID, DestReg);
+ return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID, DestReg);
+}
- MachineBasicBlock::iterator MII = I;
- return BuildMI(BB, MII, DL, MCID, DestReg);
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
+ unsigned DestReg) {
+ return BuildMI(BB, *I, DL, MCID, DestReg);
}
/// This version of the builder inserts the newly-built instruction before the
@@ -295,7 +302,7 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
/// destination register.
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
- DebugLoc DL,
+ const DebugLoc &DL,
const MCInstrDesc &MCID) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -305,7 +312,7 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::instr_iterator I,
- DebugLoc DL,
+ const DebugLoc &DL,
const MCInstrDesc &MCID) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -313,23 +320,25 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, MI);
}
-inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineInstr *I,
- DebugLoc DL,
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I,
+ const DebugLoc &DL,
const MCInstrDesc &MCID) {
- if (I->isInsideBundle()) {
- MachineBasicBlock::instr_iterator MII(I);
- return BuildMI(BB, MII, DL, MCID);
- }
+ // Calling the overload for instr_iterator is always correct. However, the
+ // definition is not available in headers, so inline the check.
+ if (I.isInsideBundle())
+ return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID);
+ return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID);
+}
- MachineBasicBlock::iterator MII = I;
- return BuildMI(BB, MII, DL, MCID);
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I,
+ const DebugLoc &DL,
+ const MCInstrDesc &MCID) {
+ return BuildMI(BB, *I, DL, MCID);
}
/// This version of the builder inserts the newly-built instruction at the end
/// of the given MachineBasicBlock, and does NOT take a destination register.
-inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
- DebugLoc DL,
+inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL,
const MCInstrDesc &MCID) {
return BuildMI(*BB, BB->end(), DL, MCID);
}
@@ -337,10 +346,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
/// This version of the builder inserts the newly-built instruction at the
/// end of the given MachineBasicBlock, and sets up the first operand as a
/// destination virtual register.
-inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
- DebugLoc DL,
- const MCInstrDesc &MCID,
- unsigned DestReg) {
+inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL,
+ const MCInstrDesc &MCID, unsigned DestReg) {
return BuildMI(*BB, BB->end(), DL, MCID, DestReg);
}
@@ -348,47 +355,19 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
/// for either a value in a register or a register-indirect+offset
/// address. The convention is that a DBG_VALUE is indirect iff the
/// second operand is an immediate.
-inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL,
- const MCInstrDesc &MCID, bool IsIndirect,
- unsigned Reg, unsigned Offset,
- const MDNode *Variable, const MDNode *Expr) {
- assert(isa<DILocalVariable>(Variable) && "not a variable");
- assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
- assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
- "Expected inlined-at fields to agree");
- if (IsIndirect)
- return BuildMI(MF, DL, MCID)
- .addReg(Reg, RegState::Debug)
- .addImm(Offset)
- .addMetadata(Variable)
- .addMetadata(Expr);
- else {
- assert(Offset == 0 && "A direct address cannot have an offset.");
- return BuildMI(MF, DL, MCID)
- .addReg(Reg, RegState::Debug)
- .addReg(0U, RegState::Debug)
- .addMetadata(Variable)
- .addMetadata(Expr);
- }
-}
+MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ unsigned Reg, unsigned Offset,
+ const MDNode *Variable, const MDNode *Expr);
/// This version of the builder builds a DBG_VALUE intrinsic
/// for either a value in a register or a register-indirect+offset
/// address and inserts it at position I.
-inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineBasicBlock::iterator I, DebugLoc DL,
- const MCInstrDesc &MCID, bool IsIndirect,
- unsigned Reg, unsigned Offset,
- const MDNode *Variable, const MDNode *Expr) {
- assert(isa<DILocalVariable>(Variable) && "not a variable");
- assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
- MachineFunction &MF = *BB.getParent();
- MachineInstr *MI =
- BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr);
- BB.insert(I, MI);
- return MachineInstrBuilder(MF, MI);
-}
-
+MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ unsigned Reg, unsigned Offset,
+ const MDNode *Variable, const MDNode *Expr);
inline unsigned getDefRegState(bool B) {
return B ? RegState::Define : 0;
@@ -412,6 +391,17 @@ inline unsigned getDebugRegState(bool B) {
return B ? RegState::Debug : 0;
}
+/// Get all register state flags from machine operand \p RegOp.
+inline unsigned getRegState(const MachineOperand &RegOp) {
+ assert(RegOp.isReg() && "Not a register operand");
+ return getDefRegState(RegOp.isDef()) |
+ getImplRegState(RegOp.isImplicit()) |
+ getKillRegState(RegOp.isKill()) |
+ getDeadRegState(RegOp.isDead()) |
+ getUndefRegState(RegOp.isUndef()) |
+ getInternalReadRegState(RegOp.isInternalRead()) |
+ getDebugRegState(RegOp.isDebug());
+}
/// Helper class for constructing bundles of MachineInstrs.
///
@@ -426,28 +416,26 @@ class MIBundleBuilder {
public:
/// Create an MIBundleBuilder that inserts instructions into a new bundle in
/// BB above the bundle or instruction at Pos.
- MIBundleBuilder(MachineBasicBlock &BB,
- MachineBasicBlock::iterator Pos)
- : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {}
+ MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator Pos)
+ : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {}
/// Create a bundle from the sequence of instructions between B and E.
- MIBundleBuilder(MachineBasicBlock &BB,
- MachineBasicBlock::iterator B,
+ MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E)
- : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) {
+ : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) {
assert(B != E && "No instructions to bundle");
++B;
while (B != E) {
- MachineInstr *MI = B;
+ MachineInstr &MI = *B;
++B;
- MI->bundleWithPred();
+ MI.bundleWithPred();
}
}
/// Create an MIBundleBuilder representing an existing instruction or bundle
/// that has MI as its head.
explicit MIBundleBuilder(MachineInstr *MI)
- : MBB(*MI->getParent()), Begin(MI), End(getBundleEnd(MI)) {}
+ : MBB(*MI->getParent()), Begin(MI), End(getBundleEnd(*MI)) {}
/// Return a reference to the basic block containing this bundle.
MachineBasicBlock &getMBB() const { return MBB; }
diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h
index 4e88606c05a7e..c0033a5148cf5 100644
--- a/include/llvm/CodeGen/MachineInstrBundle.h
+++ b/include/llvm/CodeGen/MachineInstrBundle.h
@@ -43,23 +43,22 @@ bool finalizeBundles(MachineFunction &MF);
/// getBundleStart - Returns the first instruction in the bundle containing MI.
///
-inline MachineInstr *getBundleStart(MachineInstr *MI) {
+inline MachineInstr &getBundleStart(MachineInstr &MI) {
MachineBasicBlock::instr_iterator I(MI);
while (I->isBundledWithPred())
--I;
- return &*I;
+ return *I;
}
-inline const MachineInstr *getBundleStart(const MachineInstr *MI) {
+inline const MachineInstr &getBundleStart(const MachineInstr &MI) {
MachineBasicBlock::const_instr_iterator I(MI);
while (I->isBundledWithPred())
--I;
- return &*I;
+ return *I;
}
/// Return an iterator pointing beyond the bundle containing MI.
-inline MachineBasicBlock::instr_iterator
-getBundleEnd(MachineInstr *MI) {
+inline MachineBasicBlock::instr_iterator getBundleEnd(MachineInstr &MI) {
MachineBasicBlock::instr_iterator I(MI);
while (I->isBundledWithSucc())
++I;
@@ -68,7 +67,7 @@ getBundleEnd(MachineInstr *MI) {
/// Return an iterator pointing beyond the bundle containing MI.
inline MachineBasicBlock::const_instr_iterator
-getBundleEnd(const MachineInstr *MI) {
+getBundleEnd(const MachineInstr &MI) {
MachineBasicBlock::const_instr_iterator I(MI);
while (I->isBundledWithSucc())
++I;
@@ -114,12 +113,12 @@ protected:
/// @param MI The instruction to examine.
/// @param WholeBundle When true, visit all operands on the entire bundle.
///
- explicit MachineOperandIteratorBase(MachineInstr *MI, bool WholeBundle) {
+ explicit MachineOperandIteratorBase(MachineInstr &MI, bool WholeBundle) {
if (WholeBundle) {
- InstrI = getBundleStart(MI)->getIterator();
- InstrE = MI->getParent()->instr_end();
+ InstrI = getBundleStart(MI).getIterator();
+ InstrE = MI.getParent()->instr_end();
} else {
- InstrI = InstrE = MI->getIterator();
+ InstrI = InstrE = MI.getIterator();
++InstrE;
}
OpI = InstrI->operands_begin();
@@ -184,10 +183,16 @@ public:
/// Reg or a super-register is read. The full register is read.
bool FullyRead;
- /// Reg is FullyDefined and all defs of reg or an overlapping register are
- /// dead.
+ /// Either:
+ /// - Reg is FullyDefined and all defs of reg or an overlapping
+ /// register are dead, or
+ /// - Reg is completely dead because "defined" by a clobber.
bool DeadDef;
+ /// Reg is Defined and all defs of reg or an overlapping register are
+ /// dead.
+ bool PartialDeadDef;
+
/// There is a use operand of reg or a super-register with kill flag set.
bool Killed;
};
@@ -216,7 +221,7 @@ public:
///
class MIOperands : public MachineOperandIteratorBase {
public:
- MIOperands(MachineInstr *MI) : MachineOperandIteratorBase(MI, false) {}
+ MIOperands(MachineInstr &MI) : MachineOperandIteratorBase(MI, false) {}
MachineOperand &operator* () const { return deref(); }
MachineOperand *operator->() const { return &deref(); }
};
@@ -225,8 +230,8 @@ public:
///
class ConstMIOperands : public MachineOperandIteratorBase {
public:
- ConstMIOperands(const MachineInstr *MI)
- : MachineOperandIteratorBase(const_cast<MachineInstr*>(MI), false) {}
+ ConstMIOperands(const MachineInstr &MI)
+ : MachineOperandIteratorBase(const_cast<MachineInstr &>(MI), false) {}
const MachineOperand &operator* () const { return deref(); }
const MachineOperand *operator->() const { return &deref(); }
};
@@ -236,7 +241,7 @@ public:
///
class MIBundleOperands : public MachineOperandIteratorBase {
public:
- MIBundleOperands(MachineInstr *MI) : MachineOperandIteratorBase(MI, true) {}
+ MIBundleOperands(MachineInstr &MI) : MachineOperandIteratorBase(MI, true) {}
MachineOperand &operator* () const { return deref(); }
MachineOperand *operator->() const { return &deref(); }
};
@@ -246,8 +251,8 @@ public:
///
class ConstMIBundleOperands : public MachineOperandIteratorBase {
public:
- ConstMIBundleOperands(const MachineInstr *MI)
- : MachineOperandIteratorBase(const_cast<MachineInstr*>(MI), true) {}
+ ConstMIBundleOperands(const MachineInstr &MI)
+ : MachineOperandIteratorBase(const_cast<MachineInstr &>(MI), true) {}
const MachineOperand &operator* () const { return deref(); }
const MachineOperand *operator->() const { return &deref(); }
};
diff --git a/include/llvm/CodeGen/MachineInstrBundleIterator.h b/include/llvm/CodeGen/MachineInstrBundleIterator.h
new file mode 100644
index 0000000000000..45a9a188f90ed
--- /dev/null
+++ b/include/llvm/CodeGen/MachineInstrBundleIterator.h
@@ -0,0 +1,92 @@
+//===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines an iterator class that bundles MachineInstr.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
+#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
+
+#include "llvm/ADT/ilist.h"
+#include <iterator>
+
+namespace llvm {
+
+/// MachineBasicBlock iterator that automatically skips over MIs that are
+/// inside bundles (i.e. walk top level MIs only).
+template <typename Ty>
+class MachineInstrBundleIterator
+ : public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
+ typedef ilist_iterator<Ty> instr_iterator;
+ instr_iterator MII;
+
+public:
+ MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {}
+
+ MachineInstrBundleIterator(Ty &MI) : MII(MI) {
+ assert(!MI.isBundledWithPred() && "It's not legal to initialize "
+ "MachineInstrBundleIterator with a "
+ "bundled MI");
+ }
+ MachineInstrBundleIterator(Ty *MI) : MII(MI) {
+ // FIXME: This conversion should be explicit.
+ assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
+ "MachineInstrBundleIterator "
+ "with a bundled MI");
+ }
+ // Template allows conversion from const to nonconst.
+ template <class OtherTy>
+ MachineInstrBundleIterator(const MachineInstrBundleIterator<OtherTy> &I)
+ : MII(I.getInstrIterator()) {}
+ MachineInstrBundleIterator() : MII(nullptr) {}
+
+ Ty &operator*() const { return *MII; }
+ Ty *operator->() const { return &operator*(); }
+
+ // FIXME: This conversion should be explicit.
+ operator Ty *() const { return MII.getNodePtrUnchecked(); }
+
+ bool operator==(const MachineInstrBundleIterator &X) const {
+ return MII == X.MII;
+ }
+ bool operator!=(const MachineInstrBundleIterator &X) const {
+ return !operator==(X);
+ }
+
+ // Increment and decrement operators...
+ MachineInstrBundleIterator &operator--() {
+ do
+ --MII;
+ while (MII->isBundledWithPred());
+ return *this;
+ }
+ MachineInstrBundleIterator &operator++() {
+ while (MII->isBundledWithSucc())
+ ++MII;
+ ++MII;
+ return *this;
+ }
+ MachineInstrBundleIterator operator--(int) {
+ MachineInstrBundleIterator Temp = *this;
+ --*this;
+ return Temp;
+ }
+ MachineInstrBundleIterator operator++(int) {
+ MachineInstrBundleIterator Temp = *this;
+ ++*this;
+ return Temp;
+ }
+
+ instr_iterator getInstrIterator() const { return MII; }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h
index 4868b7363f824..224a2a1aa59f5 100644
--- a/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/include/llvm/CodeGen/MachineLoopInfo.h
@@ -44,14 +44,14 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> {
public:
MachineLoop();
- /// getTopBlock - Return the "top" block in the loop, which is the first
- /// block in the linear layout, ignoring any parts of the loop not
- /// contiguous with the part the contains the header.
+ /// Return the "top" block in the loop, which is the first block in the linear
+ /// layout, ignoring any parts of the loop not contiguous with the part that
+ /// contains the header.
MachineBasicBlock *getTopBlock();
- /// getBottomBlock - Return the "bottom" block in the loop, which is the last
- /// block in the linear layout, ignoring any parts of the loop not
- /// contiguous with the part the contains the header.
+ /// Return the "bottom" block in the loop, which is the last block in the
+ /// linear layout, ignoring any parts of the loop not contiguous with the part
+ /// that contains the header.
MachineBasicBlock *getBottomBlock();
void dump() const;
@@ -81,72 +81,64 @@ public:
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
- /// iterator/begin/end - The interface to the top-level loops in the current
- /// function.
- ///
+ /// The iterator interface to the top-level loops in the current function.
typedef LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator iterator;
inline iterator begin() const { return LI.begin(); }
inline iterator end() const { return LI.end(); }
bool empty() const { return LI.empty(); }
- /// getLoopFor - Return the inner most loop that BB lives in. If a basic
- /// block is in no loop (for example the entry node), null is returned.
- ///
+ /// Return the innermost loop that BB lives in. If a basic block is in no loop
+ /// (for example the entry node), null is returned.
inline MachineLoop *getLoopFor(const MachineBasicBlock *BB) const {
return LI.getLoopFor(BB);
}
- /// operator[] - same as getLoopFor...
- ///
+ /// Same as getLoopFor.
inline const MachineLoop *operator[](const MachineBasicBlock *BB) const {
return LI.getLoopFor(BB);
}
- /// getLoopDepth - Return the loop nesting level of the specified block...
- ///
+ /// Return the loop nesting level of the specified block.
inline unsigned getLoopDepth(const MachineBasicBlock *BB) const {
return LI.getLoopDepth(BB);
}
- // isLoopHeader - True if the block is a loop header node
+ /// True if the block is a loop header node.
inline bool isLoopHeader(const MachineBasicBlock *BB) const {
return LI.isLoopHeader(BB);
}
- /// runOnFunction - Calculate the natural loop information.
- ///
+ /// Calculate the natural loop information.
bool runOnMachineFunction(MachineFunction &F) override;
void releaseMemory() override { LI.releaseMemory(); }
void getAnalysisUsage(AnalysisUsage &AU) const override;
- /// removeLoop - This removes the specified top-level loop from this loop info
- /// object. The loop is not deleted, as it will presumably be inserted into
- /// another loop.
+ /// This removes the specified top-level loop from this loop info object. The
+ /// loop is not deleted, as it will presumably be inserted into another loop.
inline MachineLoop *removeLoop(iterator I) { return LI.removeLoop(I); }
- /// changeLoopFor - Change the top-level loop that contains BB to the
- /// specified loop. This should be used by transformations that restructure
- /// the loop hierarchy tree.
+ /// Change the top-level loop that contains BB to the specified loop. This
+ /// should be used by transformations that restructure the loop hierarchy
+ /// tree.
inline void changeLoopFor(MachineBasicBlock *BB, MachineLoop *L) {
LI.changeLoopFor(BB, L);
}
- /// changeTopLevelLoop - Replace the specified loop in the top-level loops
- /// list with the indicated loop.
+ /// Replace the specified loop in the top-level loops list with the indicated
+ /// loop.
inline void changeTopLevelLoop(MachineLoop *OldLoop, MachineLoop *NewLoop) {
LI.changeTopLevelLoop(OldLoop, NewLoop);
}
- /// addTopLevelLoop - This adds the specified loop to the collection of
- /// top-level loops.
+ /// This adds the specified loop to the collection of top-level loops.
inline void addTopLevelLoop(MachineLoop *New) {
LI.addTopLevelLoop(New);
}
- /// removeBlock - This method completely removes BB from all data structures,
- /// including all of the Loop objects it is nested in and our mapping from
+ /// This method completely removes BB from all data structures, including all
+ /// of the Loop objects it is nested in and our mapping from
/// MachineBasicBlocks to loops.
void removeBlock(MachineBasicBlock *BB) {
LI.removeBlock(BB);
diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h
index 1ca0d90465a4a..5fa7058733b37 100644
--- a/include/llvm/CodeGen/MachineMemOperand.h
+++ b/include/llvm/CodeGen/MachineMemOperand.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H
#define LLVM_CODEGEN_MACHINEMEMOPERAND_H
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/IR/Metadata.h"
@@ -30,12 +31,11 @@ class raw_ostream;
class MachineFunction;
class ModuleSlotTracker;
-/// MachinePointerInfo - This class contains a discriminated union of
-/// information about pointers in memory operands, relating them back to LLVM IR
-/// or to virtual locations (such as frame indices) that are exposed during
-/// codegen.
+/// This class contains a discriminated union of information about pointers in
+/// memory operands, relating them back to LLVM IR or to virtual locations (such
+/// as frame indices) that are exposed during codegen.
struct MachinePointerInfo {
- /// V - This is the IR pointer value for the access, or it is null if unknown.
+ /// This is the IR pointer value for the access, or it is null if unknown.
/// If this is null, then the access is to a pointer in the default address
/// space.
PointerUnion<const Value *, const PseudoSourceValue *> V;
@@ -57,34 +57,30 @@ struct MachinePointerInfo {
return MachinePointerInfo(V.get<const PseudoSourceValue*>(), Offset+O);
}
- /// getAddrSpace - Return the LLVM IR address space number that this pointer
- /// points into.
+ /// Return the LLVM IR address space number that this pointer points into.
unsigned getAddrSpace() const;
- /// getConstantPool - Return a MachinePointerInfo record that refers to the
- /// constant pool.
+ /// Return a MachinePointerInfo record that refers to the constant pool.
static MachinePointerInfo getConstantPool(MachineFunction &MF);
- /// getFixedStack - Return a MachinePointerInfo record that refers to the
- /// the specified FrameIndex.
+ /// Return a MachinePointerInfo record that refers to the specified
+ /// FrameIndex.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI,
int64_t Offset = 0);
- /// getJumpTable - Return a MachinePointerInfo record that refers to a
- /// jump table entry.
+ /// Return a MachinePointerInfo record that refers to a jump table entry.
static MachinePointerInfo getJumpTable(MachineFunction &MF);
- /// getGOT - Return a MachinePointerInfo record that refers to a
- /// GOT entry.
+ /// Return a MachinePointerInfo record that refers to a GOT entry.
static MachinePointerInfo getGOT(MachineFunction &MF);
- /// getStack - stack pointer relative access.
+ /// Stack pointer relative access.
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset);
};
//===----------------------------------------------------------------------===//
-/// MachineMemOperand - A description of a memory reference used in the backend.
+/// A description of a memory reference used in the backend.
/// Instead of holding a StoreInst or LoadInst, this class holds the address
/// Value of the reference along with a byte size and offset. This allows it
/// to describe lowered loads and stores. Also, the special PseudoSourceValue
@@ -92,43 +88,50 @@ struct MachinePointerInfo {
/// that aren't explicit in the regular LLVM IR.
///
class MachineMemOperand {
- MachinePointerInfo PtrInfo;
- uint64_t Size;
- unsigned Flags;
- AAMDNodes AAInfo;
- const MDNode *Ranges;
-
public:
/// Flags values. These may be or'd together.
- enum MemOperandFlags {
+ enum Flags : uint16_t {
+ // No flags set.
+ MONone = 0,
/// The memory access reads data.
- MOLoad = 1,
+ MOLoad = 1u << 0,
/// The memory access writes data.
- MOStore = 2,
+ MOStore = 1u << 1,
/// The memory access is volatile.
- MOVolatile = 4,
+ MOVolatile = 1u << 2,
/// The memory access is non-temporal.
- MONonTemporal = 8,
+ MONonTemporal = 1u << 3,
/// The memory access is invariant.
- MOInvariant = 16,
- // Target hints allow target passes to annotate memory operations.
- MOTargetStartBit = 5,
- MOTargetNumBits = 3,
- // This is the number of bits we need to represent flags.
- MOMaxBits = 8
+ MOInvariant = 1u << 4,
+
+ // Reserved for use by target-specific passes.
+ MOTargetFlag1 = 1u << 5,
+ MOTargetFlag2 = 1u << 6,
+ MOTargetFlag3 = 1u << 7,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ MOTargetFlag3)
};
- /// MachineMemOperand - Construct an MachineMemOperand object with the
- /// specified PtrInfo, flags, size, and base alignment.
- MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s,
+private:
+ MachinePointerInfo PtrInfo;
+ uint64_t Size;
+ Flags FlagVals;
+ uint16_t BaseAlignLog2; // log_2(base_alignment) + 1
+ AAMDNodes AAInfo;
+ const MDNode *Ranges;
+
+public:
+ /// Construct a MachineMemOperand object with the specified PtrInfo, flags,
+ /// size, and base alignment.
+ MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s,
unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
const MachinePointerInfo &getPointerInfo() const { return PtrInfo; }
- /// getValue - Return the base address of the memory access. This may either
- /// be a normal LLVM IR Value, or one of the special values used in CodeGen.
+ /// Return the base address of the memory access. This may either be a normal
+ /// LLVM IR Value, or one of the special values used in CodeGen.
/// Special values are those obtained via
/// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and
/// other PseudoSourceValue member functions which return objects which stand
@@ -142,59 +145,58 @@ public:
const void *getOpaqueValue() const { return PtrInfo.V.getOpaqueValue(); }
- /// getFlags - Return the raw flags of the source value, \see MemOperandFlags.
- unsigned int getFlags() const { return Flags & ((1 << MOMaxBits) - 1); }
+ /// Return the raw flags of the source value, \see Flags.
+ Flags getFlags() const { return FlagVals; }
/// Bitwise OR the current flags with the given flags.
- void setFlags(unsigned f) { Flags |= (f & ((1 << MOMaxBits) - 1)); }
+ void setFlags(Flags f) { FlagVals |= f; }
- /// getOffset - For normal values, this is a byte offset added to the base
- /// address. For PseudoSourceValue::FPRel values, this is the FrameIndex
- /// number.
+ /// For normal values, this is a byte offset added to the base address.
+ /// For PseudoSourceValue::FPRel values, this is the FrameIndex number.
int64_t getOffset() const { return PtrInfo.Offset; }
unsigned getAddrSpace() const { return PtrInfo.getAddrSpace(); }
- /// getSize - Return the size in bytes of the memory reference.
+ /// Return the size in bytes of the memory reference.
uint64_t getSize() const { return Size; }
- /// getAlignment - Return the minimum known alignment in bytes of the
- /// actual memory reference.
+ /// Return the minimum known alignment in bytes of the actual memory
+ /// reference.
uint64_t getAlignment() const;
- /// getBaseAlignment - Return the minimum known alignment in bytes of the
- /// base address, without the offset.
- uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; }
+ /// Return the minimum known alignment in bytes of the base address, without
+ /// the offset.
+ uint64_t getBaseAlignment() const { return (1u << BaseAlignLog2) >> 1; }
- /// getAAInfo - Return the AA tags for the memory reference.
+ /// Return the AA tags for the memory reference.
AAMDNodes getAAInfo() const { return AAInfo; }
- /// getRanges - Return the range tag for the memory reference.
+ /// Return the range tag for the memory reference.
const MDNode *getRanges() const { return Ranges; }
- bool isLoad() const { return Flags & MOLoad; }
- bool isStore() const { return Flags & MOStore; }
- bool isVolatile() const { return Flags & MOVolatile; }
- bool isNonTemporal() const { return Flags & MONonTemporal; }
- bool isInvariant() const { return Flags & MOInvariant; }
+ bool isLoad() const { return FlagVals & MOLoad; }
+ bool isStore() const { return FlagVals & MOStore; }
+ bool isVolatile() const { return FlagVals & MOVolatile; }
+ bool isNonTemporal() const { return FlagVals & MONonTemporal; }
+ bool isInvariant() const { return FlagVals & MOInvariant; }
- /// isUnordered - Returns true if this memory operation doesn't have any
- /// ordering constraints other than normal aliasing. Volatile and atomic
- /// memory operations can't be reordered.
+ /// Returns true if this memory operation doesn't have any ordering
+ /// constraints other than normal aliasing. Volatile and atomic memory
+ /// operations can't be reordered.
///
/// Currently, we don't model the difference between volatile and atomic
/// operations. They should retain their ordering relative to all memory
/// operations.
bool isUnordered() const { return !isVolatile(); }
- /// refineAlignment - Update this MachineMemOperand to reflect the alignment
- /// of MMO, if it has a greater alignment. This must only be used when the
- /// new alignment applies to all users of this MachineMemOperand.
+ /// Update this MachineMemOperand to reflect the alignment of MMO, if it has a
+ /// greater alignment. This must only be used when the new alignment applies
+ /// to all users of this MachineMemOperand.
void refineAlignment(const MachineMemOperand *MMO);
- /// setValue - Change the SourceValue for this MachineMemOperand. This
- /// should only be used when an object is being relocated and all references
- /// to it are being updated.
+ /// Change the SourceValue for this MachineMemOperand. This should only be
+ /// used when an object is being relocated and all references to it are being
+ /// updated.
void setValue(const Value *NewSV) { PtrInfo.V = NewSV; }
void setValue(const PseudoSourceValue *NewSV) { PtrInfo.V = NewSV; }
void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; }
diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h
index e7472145e71f5..f9fa6999073fc 100644
--- a/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -23,44 +23,35 @@ class MCSymbol;
/// MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation
/// for MachO targets.
class MachineModuleInfoMachO : public MachineModuleInfoImpl {
- /// FnStubs - Darwin '$stub' stubs. The key is something like "Lfoo$stub",
- /// the value is something like "_foo".
- DenseMap<MCSymbol *, StubValueTy> FnStubs;
-
/// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like
/// "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra bit
/// is true if this GV is external.
DenseMap<MCSymbol *, StubValueTy> GVStubs;
- /// HiddenGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like
- /// "Lfoo$non_lazy_ptr", the value is something like "_foo". Unlike GVStubs
- /// these are for things with hidden visibility. The extra bit is true if
- /// this GV is external.
- DenseMap<MCSymbol *, StubValueTy> HiddenGVStubs;
+ /// ThreadLocalGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something
+ /// like "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra
+ /// bit is true if this GV is external.
+ DenseMap<MCSymbol *, StubValueTy> ThreadLocalGVStubs;
virtual void anchor(); // Out of line virtual method.
public:
MachineModuleInfoMachO(const MachineModuleInfo &) {}
- StubValueTy &getFnStubEntry(MCSymbol *Sym) {
- assert(Sym && "Key cannot be null");
- return FnStubs[Sym];
- }
-
StubValueTy &getGVStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
return GVStubs[Sym];
}
- StubValueTy &getHiddenGVStubEntry(MCSymbol *Sym) {
+ StubValueTy &getThreadLocalGVStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
- return HiddenGVStubs[Sym];
+ return ThreadLocalGVStubs[Sym];
}
/// Accessor methods to return the set of stubs in sorted order.
- SymbolListTy GetFnStubList() { return getSortedStubs(FnStubs); }
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
- SymbolListTy GetHiddenGVStubList() { return getSortedStubs(HiddenGVStubs); }
+ SymbolListTy GetThreadLocalGVStubList() {
+ return getSortedStubs(ThreadLocalGVStubs);
+ }
};
/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index c43e47c36d060..ee0a9cf11e6ab 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -534,6 +534,15 @@ public:
Contents.MBB = MBB;
}
+ /// Sets value of register mask operand referencing Mask. The
+ /// operand does not take ownership of the memory referenced by Mask, it must
+ /// remain valid for the lifetime of the operand. See CreateRegMask().
+ /// Any physreg with a 0 bit in the mask is clobbered by the instruction.
+ void setRegMask(const uint32_t *RegMaskPtr) {
+ assert(isRegMask() && "Wrong MachineOperand mutator");
+ Contents.RegMask = RegMaskPtr;
+ }
+
//===--------------------------------------------------------------------===//
// Other methods.
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 04191bc1b74ff..07d2d016f274b 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -16,7 +16,10 @@
#include "llvm/ADT/BitVector.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/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/Target/TargetRegisterInfo.h"
@@ -26,6 +29,10 @@
namespace llvm {
class PSetIterator;
+/// Convenient type to represent either a register class or a register bank.
+typedef PointerUnion<const TargetRegisterClass *, const RegisterBank *>
+ RegClassOrRegBank;
+
/// MachineRegisterInfo - Keep track of information for virtual and physical
/// registers, including vreg register classes, use/def chains for registers,
/// etc.
@@ -40,18 +47,9 @@ public:
};
private:
- const MachineFunction *MF;
+ MachineFunction *MF;
Delegate *TheDelegate;
- /// IsSSA - True when the machine function is in SSA form and virtual
- /// registers have a single def.
- bool IsSSA;
-
- /// TracksLiveness - True while register liveness is being tracked accurately.
- /// Basic block live-in lists, kill flags, and implicit defs may not be
- /// accurate when after this flag is cleared.
- bool TracksLiveness;
-
/// True if subregister liveness is tracked.
bool TracksSubRegLiveness;
@@ -59,8 +57,9 @@ private:
///
/// Each element in this list contains the register class of the vreg and the
/// start of the use/def list for the register.
- IndexedMap<std::pair<const TargetRegisterClass*, MachineOperand*>,
- VirtReg2IndexFunctor> VRegInfo;
+ IndexedMap<std::pair<RegClassOrRegBank, MachineOperand *>,
+ VirtReg2IndexFunctor>
+ VRegInfo;
/// RegAllocHints - This vector records register allocation hints for virtual
/// registers. For each virtual register, it keeps a register and hint type
@@ -105,6 +104,18 @@ private:
/// started.
BitVector ReservedRegs;
+ typedef DenseMap<unsigned, unsigned> VRegToSizeMap;
+ /// Map generic virtual registers to their actual size.
+ mutable std::unique_ptr<VRegToSizeMap> VRegToSize;
+
+ /// Accessor for VRegToSize. This accessor should only be used
+ /// by global-isel related work.
+ VRegToSizeMap &getVRegToSize() const {
+ if (!VRegToSize)
+ VRegToSize.reset(new VRegToSizeMap);
+ return *VRegToSize.get();
+ }
+
/// Keep track of the physical registers that are live in to the function.
/// Live in values are typically arguments in registers. LiveIn values are
/// allowed to have virtual registers associated with them, stored in the
@@ -114,7 +125,7 @@ private:
MachineRegisterInfo(const MachineRegisterInfo&) = delete;
void operator=(const MachineRegisterInfo&) = delete;
public:
- explicit MachineRegisterInfo(const MachineFunction *MF);
+ explicit MachineRegisterInfo(MachineFunction *MF);
const TargetRegisterInfo *getTargetRegisterInfo() const {
return MF->getSubtarget().getRegisterInfo();
@@ -148,27 +159,32 @@ public:
// The TwoAddressInstructionPass and PHIElimination passes take the machine
// function out of SSA form when they introduce multiple defs per virtual
// register.
- bool isSSA() const { return IsSSA; }
+ bool isSSA() const {
+ return MF->getProperties().hasProperty(
+ MachineFunctionProperties::Property::IsSSA);
+ }
// leaveSSA - Indicates that the machine function is no longer in SSA form.
- void leaveSSA() { IsSSA = false; }
+ void leaveSSA() {
+ MF->getProperties().clear(MachineFunctionProperties::Property::IsSSA);
+ }
/// tracksLiveness - Returns true when tracking register liveness accurately.
- ///
- /// While this flag is true, register liveness information in basic block
- /// live-in lists and machine instruction operands is accurate. This means it
- /// can be used to change the code in ways that affect the values in
- /// registers, for example by the register scavenger.
- ///
- /// When this flag is false, liveness is no longer reliable.
- bool tracksLiveness() const { return TracksLiveness; }
+ /// (see MachineFUnctionProperties::Property description for details)
+ bool tracksLiveness() const {
+ return MF->getProperties().hasProperty(
+ MachineFunctionProperties::Property::TracksLiveness);
+ }
/// invalidateLiveness - Indicates that register liveness is no longer being
/// tracked accurately.
///
/// This should be called by late passes that invalidate the liveness
/// information.
- void invalidateLiveness() { TracksLiveness = false; }
+ void invalidateLiveness() {
+ MF->getProperties().clear(
+ MachineFunctionProperties::Property::TracksLiveness);
+ }
/// Returns true if liveness for register class @p RC should be tracked at
/// the subregister level.
@@ -375,8 +391,8 @@ public:
/// specified register (it may be live-in).
bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); }
- /// hasOneDef - Return true if there is exactly one instruction defining the
- /// specified register.
+ /// Return true if there is exactly one operand defining the specified
+ /// register.
bool hasOneDef(unsigned RegNo) const {
def_iterator DI = def_begin(RegNo);
if (DI == def_end())
@@ -551,9 +567,47 @@ public:
// Virtual Register Info
//===--------------------------------------------------------------------===//
- /// getRegClass - Return the register class of the specified virtual register.
+ /// Return the register class of the specified virtual register.
+ /// This shouldn't be used directly unless \p Reg has a register class.
+ /// \see getRegClassOrNull when this might happen.
///
const TargetRegisterClass *getRegClass(unsigned Reg) const {
+ assert(VRegInfo[Reg].first.is<const TargetRegisterClass *>() &&
+ "Register class not set, wrong accessor");
+ return VRegInfo[Reg].first.get<const TargetRegisterClass *>();
+ }
+
+ /// Return the register class of \p Reg, or null if Reg has not been assigned
+ /// a register class yet.
+ ///
+ /// \note A null register class can only happen when these two
+ /// conditions are met:
+ /// 1. Generic virtual registers are created.
+ /// 2. The machine function has not completely been through the
+ /// instruction selection process.
+ /// None of this condition is possible without GlobalISel for now.
+ /// In other words, if GlobalISel is not used or if the query happens after
+ /// the select pass, using getRegClass is safe.
+ const TargetRegisterClass *getRegClassOrNull(unsigned Reg) const {
+ const RegClassOrRegBank &Val = VRegInfo[Reg].first;
+ return Val.dyn_cast<const TargetRegisterClass *>();
+ }
+
+ /// Return the register bank of \p Reg, or null if Reg has not been assigned
+ /// a register bank or has been assigned a register class.
+ /// \note It is possible to get the register bank from the register class via
+ /// RegisterBankInfo::getRegBankFromRegClass.
+ ///
+ const RegisterBank *getRegBankOrNull(unsigned Reg) const {
+ const RegClassOrRegBank &Val = VRegInfo[Reg].first;
+ return Val.dyn_cast<const RegisterBank *>();
+ }
+
+ /// Return the register bank or register class of \p Reg.
+ /// \note Before the register bank gets assigned (i.e., before the
+ /// RegBankSelect pass) \p Reg may not have either.
+ ///
+ const RegClassOrRegBank &getRegClassOrRegBank(unsigned Reg) const {
return VRegInfo[Reg].first;
}
@@ -561,6 +615,10 @@ public:
///
void setRegClass(unsigned Reg, const TargetRegisterClass *RC);
+ /// Set the register bank to \p RegBank for \p Reg.
+ ///
+ void setRegBank(unsigned Reg, const RegisterBank &RegBank);
+
/// constrainRegClass - Constrain the register class of the specified virtual
/// register to be a common subclass of RC and the current register class,
/// but only if the new class has at least MinNumRegs registers. Return the
@@ -587,6 +645,19 @@ public:
///
unsigned createVirtualRegister(const TargetRegisterClass *RegClass);
+ /// Get the size in bits of \p VReg or 0 if VReg is not a generic
+ /// (target independent) virtual register.
+ unsigned getSize(unsigned VReg) const;
+
+ /// Set the size in bits of \p VReg to \p Size.
+ /// Although the size should be set at build time, mir infrastructure
+ /// is not yet able to do it.
+ void setSize(unsigned VReg, unsigned Size);
+
+ /// Create and return a new generic virtual register with a size of \p Size.
+ /// \pre Size > 0.
+ unsigned createGenericVirtualRegister(unsigned Size);
+
/// getNumVirtRegs - Return the number of virtual registers created.
///
unsigned getNumVirtRegs() const { return VRegInfo.size(); }
@@ -632,9 +703,10 @@ public:
/// Return true if the specified register is modified in this function.
/// This checks that no defining machine operands exist for the register or
/// any of its aliases. Definitions found on functions marked noreturn are
- /// ignored. The register is also considered modified when it is set in the
- /// UsedPhysRegMask.
- bool isPhysRegModified(unsigned PhysReg) const;
+ /// ignored, to consider them pass 'true' for optional parameter
+ /// SkipNoReturnDef. The register is also considered modified when it is set
+ /// in the UsedPhysRegMask.
+ bool isPhysRegModified(unsigned PhysReg, bool SkipNoReturnDef = false) const;
/// Return true if the specified register is modified or read in this
/// function. This checks that no machine operands exist for the register or
@@ -820,10 +892,10 @@ public:
advance();
} while (Op && Op->getParent() == P);
} else if (ByBundle) {
- MachineInstr *P = getBundleStart(Op->getParent());
+ MachineInstr &P = getBundleStart(*Op->getParent());
do {
advance();
- } while (Op && getBundleStart(Op->getParent()) == P);
+ } while (Op && &getBundleStart(*Op->getParent()) == &P);
}
return *this;
@@ -922,10 +994,10 @@ public:
advance();
} while (Op && Op->getParent() == P);
} else if (ByBundle) {
- MachineInstr *P = getBundleStart(Op->getParent());
+ MachineInstr &P = getBundleStart(*Op->getParent());
do {
advance();
- } while (Op && getBundleStart(Op->getParent()) == P);
+ } while (Op && &getBundleStart(*Op->getParent()) == &P);
}
return *this;
@@ -937,15 +1009,12 @@ public:
// Retrieve a reference to the current operand.
MachineInstr &operator*() const {
assert(Op && "Cannot dereference end iterator!");
- if (ByBundle) return *(getBundleStart(Op->getParent()));
+ if (ByBundle)
+ return getBundleStart(*Op->getParent());
return *Op->getParent();
}
- MachineInstr *operator->() const {
- assert(Op && "Cannot dereference end iterator!");
- if (ByBundle) return getBundleStart(Op->getParent());
- return Op->getParent();
- }
+ MachineInstr *operator->() const { return &operator*(); }
};
};
diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h
index 5f988ad86320f..50a7d90bf25b0 100644
--- a/include/llvm/CodeGen/MachineSSAUpdater.h
+++ b/include/llvm/CodeGen/MachineSSAUpdater.h
@@ -14,7 +14,6 @@
#ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H
#define LLVM_CODEGEN_MACHINESSAUPDATER_H
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h
index 358fd5a3732a6..06e9921790316 100644
--- a/include/llvm/CodeGen/MachineScheduler.h
+++ b/include/llvm/CodeGen/MachineScheduler.h
@@ -66,8 +66,6 @@
//
// void <SubTarget>Subtarget::
// overrideSchedPolicy(MachineSchedPolicy &Policy,
-// MachineInstr *begin,
-// MachineInstr *end,
// unsigned NumRegionInstrs) const {
// Policy.<Flag> = true;
// }
@@ -81,6 +79,7 @@
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/RegisterPressure.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
+#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include <memory>
namespace llvm {
@@ -150,6 +149,9 @@ class ScheduleDAGMI;
struct MachineSchedPolicy {
// Allow the scheduler to disable register pressure tracking.
bool ShouldTrackPressure;
+ /// Track LaneMasks to allow reordering of independent subregister writes
+ /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
+ bool ShouldTrackLaneMasks;
// Allow the scheduler to force top-down or bottom-up scheduling. If neither
// is true, the scheduler runs in both directions and converges.
@@ -160,8 +162,8 @@ struct MachineSchedPolicy {
// first.
bool DisableLatencyHeuristic;
- MachineSchedPolicy(): ShouldTrackPressure(false), OnlyTopDown(false),
- OnlyBottomUp(false), DisableLatencyHeuristic(false) {}
+ MachineSchedPolicy(): ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
+ OnlyTopDown(false), OnlyBottomUp(false), DisableLatencyHeuristic(false) {}
};
/// MachineSchedStrategy - Interface to the scheduling algorithm used by
@@ -185,6 +187,11 @@ public:
/// initializing this strategy. Called after initPolicy.
virtual bool shouldTrackPressure() const { return true; }
+ /// Returns true if lanemasks should be tracked. LaneMask tracking is
+ /// necessary to reorder independent subregister defs for the same vreg.
+ /// This has to be enabled in combination with shouldTrackPressure().
+ virtual bool shouldTrackLaneMasks() const { return false; }
+
/// Initialize the strategy after building the DAG for a new region.
virtual void initialize(ScheduleDAGMI *DAG) = 0;
@@ -212,15 +219,6 @@ public:
virtual void releaseBottomNode(SUnit *SU) = 0;
};
-/// Mutate the DAG as a postpass after normal DAG building.
-class ScheduleDAGMutation {
- virtual void anchor();
-public:
- virtual ~ScheduleDAGMutation() {}
-
- virtual void apply(ScheduleDAGMI *DAG) = 0;
-};
-
/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply
/// schedules machine instructions according to the given MachineSchedStrategy
/// without much extra book-keeping. This is the common functionality between
@@ -371,6 +369,7 @@ protected:
/// Register pressure in this region computed by initRegPressure.
bool ShouldTrackPressure;
+ bool ShouldTrackLaneMasks;
IntervalPressure RegPressure;
RegPressureTracker RPTracker;
@@ -387,13 +386,18 @@ protected:
IntervalPressure BotPressure;
RegPressureTracker BotRPTracker;
+ /// True if disconnected subregister components are already renamed.
+ /// The renaming is only done on demand if lane masks are tracked.
+ bool DisconnectedComponentsRenamed;
+
public:
ScheduleDAGMILive(MachineSchedContext *C,
std::unique_ptr<MachineSchedStrategy> S)
: ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
RegClassInfo(C->RegClassInfo), DFSResult(nullptr),
- ShouldTrackPressure(false), RPTracker(RegPressure),
- TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
+ ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
+ RPTracker(RegPressure), TopRPTracker(TopPressure),
+ BotRPTracker(BotPressure), DisconnectedComponentsRenamed(false) {}
~ScheduleDAGMILive() override;
@@ -455,6 +459,10 @@ protected:
/// bottom of the DAG region without covereing any unscheduled instruction.
void buildDAGWithRegPressure();
+ /// Release ExitSU predecessors and setup scheduler queues. Re-position
+ /// the Top RP tracker in case the region beginning has changed.
+ void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
+
/// Move an instruction and update register pressure.
void scheduleMI(SUnit *SU, bool IsTopNode);
@@ -462,7 +470,7 @@ protected:
void initRegPressure();
- void updatePressureDiffs(ArrayRef<unsigned> LiveUses);
+ void updatePressureDiffs(ArrayRef<RegisterMaskPair> LiveUses);
void updateScheduledPressure(const SUnit *SU,
const std::vector<unsigned> &NewMaxPressure);
@@ -753,9 +761,9 @@ class GenericSchedulerBase : public MachineSchedStrategy {
public:
/// Represent the type of SchedCandidate found within a single queue.
/// pickNodeBidirectional depends on these listed by decreasing priority.
- enum CandReason {
- NoCand, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax,
- ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
+ enum CandReason : uint8_t {
+ NoCand, Only1, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak,
+ RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
#ifndef NDEBUG
@@ -769,6 +777,15 @@ public:
unsigned DemandResIdx;
CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {}
+
+ bool operator==(const CandPolicy &RHS) const {
+ return ReduceLatency == RHS.ReduceLatency &&
+ ReduceResIdx == RHS.ReduceResIdx &&
+ DemandResIdx == RHS.DemandResIdx;
+ }
+ bool operator!=(const CandPolicy &RHS) const {
+ return !(*this == RHS);
+ }
};
/// Status of an instruction's critical resource consumption.
@@ -801,8 +818,8 @@ public:
// The reason for this candidate.
CandReason Reason;
- // Set of reasons that apply to multiple candidates.
- uint32_t RepeatReasonSet;
+ // Whether this candidate should be scheduled at top/bottom.
+ bool AtTop;
// Register pressure values for the best candidate.
RegPressureDelta RPDelta;
@@ -810,8 +827,17 @@ public:
// Critical resource consumption of the best candidate.
SchedResourceDelta ResDelta;
- SchedCandidate(const CandPolicy &policy)
- : Policy(policy), SU(nullptr), Reason(NoCand), RepeatReasonSet(0) {}
+ SchedCandidate() { reset(CandPolicy()); }
+ SchedCandidate(const CandPolicy &Policy) { reset(Policy); }
+
+ void reset(const CandPolicy &NewPolicy) {
+ Policy = NewPolicy;
+ SU = nullptr;
+ Reason = NoCand;
+ AtTop = false;
+ RPDelta = RegPressureDelta();
+ ResDelta = SchedResourceDelta();
+ }
bool isValid() const { return SU; }
@@ -820,13 +846,11 @@ public:
assert(Best.Reason != NoCand && "uninitialized Sched candidate");
SU = Best.SU;
Reason = Best.Reason;
+ AtTop = Best.AtTop;
RPDelta = Best.RPDelta;
ResDelta = Best.ResDelta;
}
- bool isRepeat(CandReason R) { return RepeatReasonSet & (1 << R); }
- void setRepeat(CandReason R) { RepeatReasonSet |= (1 << R); }
-
void initResourceDelta(const ScheduleDAGMI *DAG,
const TargetSchedModel *SchedModel);
};
@@ -858,6 +882,11 @@ class GenericScheduler : public GenericSchedulerBase {
SchedBoundary Top;
SchedBoundary Bot;
+ /// Candidate last picked from Top boundary.
+ SchedCandidate TopCand;
+ /// Candidate last picked from Bot boundary.
+ SchedCandidate BotCand;
+
MachineSchedPolicy RegionPolicy;
public:
GenericScheduler(const MachineSchedContext *C):
@@ -874,6 +903,10 @@ public:
return RegionPolicy.ShouldTrackPressure;
}
+ bool shouldTrackLaneMasks() const override {
+ return RegionPolicy.ShouldTrackLaneMasks;
+ }
+
void initialize(ScheduleDAGMI *dag) override;
SUnit *pickNode(bool &IsTopNode) override;
@@ -882,10 +915,12 @@ public:
void releaseTopNode(SUnit *SU) override {
Top.releaseTopNode(SU);
+ TopCand.SU = nullptr;
}
void releaseBottomNode(SUnit *SU) override {
Bot.releaseBottomNode(SU);
+ BotCand.SU = nullptr;
}
void registerRoots() override;
@@ -893,15 +928,18 @@ public:
protected:
void checkAcyclicLatency();
+ void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
+ const RegPressureTracker &RPTracker,
+ RegPressureTracker &TempTracker);
+
void tryCandidate(SchedCandidate &Cand,
SchedCandidate &TryCand,
- SchedBoundary &Zone,
- const RegPressureTracker &RPTracker,
- RegPressureTracker &TempTracker);
+ SchedBoundary *Zone);
SUnit *pickNodeBidirectional(bool &IsTopNode);
void pickNodeFromQueue(SchedBoundary &Zone,
+ const CandPolicy &ZonePolicy,
const RegPressureTracker &RPTracker,
SchedCandidate &Candidate);
diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h
index bfe6e945b6da6..06db17abaed91 100644
--- a/include/llvm/CodeGen/MachineTraceMetrics.h
+++ b/include/llvm/CodeGen/MachineTraceMetrics.h
@@ -50,6 +50,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/TargetSchedule.h"
namespace llvm {
@@ -275,24 +276,24 @@ public:
/// Return the depth and height of MI. The depth is only valid for
/// instructions in or above the trace center block. The height is only
/// valid for instructions in or below the trace center block.
- InstrCycles getInstrCycles(const MachineInstr *MI) const {
- return TE.Cycles.lookup(MI);
+ InstrCycles getInstrCycles(const MachineInstr &MI) const {
+ return TE.Cycles.lookup(&MI);
}
/// Return the slack of MI. This is the number of cycles MI can be delayed
/// before the critical path becomes longer.
/// MI must be an instruction in the trace center block.
- unsigned getInstrSlack(const MachineInstr *MI) const;
+ unsigned getInstrSlack(const MachineInstr &MI) const;
/// Return the Depth of a PHI instruction in a trace center block successor.
/// The PHI does not have to be part of the trace.
- unsigned getPHIDepth(const MachineInstr *PHI) const;
+ unsigned getPHIDepth(const MachineInstr &PHI) const;
/// A dependence is useful if the basic block of the defining instruction
/// is part of the trace of the user instruction. It is assumed that DefMI
/// dominates UseMI (see also isUsefulDominator).
- bool isDepInTrace(const MachineInstr *DefMI,
- const MachineInstr *UseMI) const;
+ bool isDepInTrace(const MachineInstr &DefMI,
+ const MachineInstr &UseMI) const;
};
/// A trace ensemble is a collection of traces selected using the same
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index 04d6ee3be531a..0bb53d1a53743 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -28,7 +28,7 @@ namespace llvm {
/// type can be represented by an MVT.
class MVT {
public:
- enum SimpleValueType {
+ enum SimpleValueType : int8_t {
// INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are
// considered extended value types.
INVALID_SIMPLE_VALUE_TYPE = -1,
@@ -142,38 +142,38 @@ class MVT {
MAX_ALLOWED_VALUETYPE = 96,
// Token - A value of type llvm::TokenTy
- token = 249,
+ token = 120,
// Metadata - This is MDNode or MDString.
- Metadata = 250,
+ Metadata = 121,
// iPTRAny - 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 = 251,
+ iPTRAny = 122,
// vAny - 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 = 252,
+ vAny = 123,
// fAny - 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 = 253,
+ fAny = 124,
// iAny - 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 = 254,
+ iAny = 125,
// iPTR - An int value the size of the pointer of the current
// target. This should only be used internal to tblgen!
- iPTR = 255,
+ iPTR = 126,
// Any - Any type. This is used for intrinsics that have overloadings.
// This is only for tblgen's consumption!
- Any = 256
+ Any = 127
};
SimpleValueType SimpleTy;
@@ -210,6 +210,13 @@ class MVT {
SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE));
}
+ /// isScalarInteger - 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.
bool isVector() const {
return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE &&
diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h
index f73383ed10007..8301ca4d85366 100644
--- a/include/llvm/CodeGen/PBQP/Graph.h
+++ b/include/llvm/CodeGen/PBQP/Graph.h
@@ -15,12 +15,11 @@
#ifndef LLVM_CODEGEN_PBQP_GRAPH_H
#define LLVM_CODEGEN_PBQP_GRAPH_H
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/Debug.h"
-#include <list>
-#include <map>
-#include <set>
+#include <algorithm>
+#include <cassert>
+#include <limits>
+#include <utility>
#include <vector>
namespace llvm {
@@ -72,7 +71,7 @@ namespace PBQP {
return std::numeric_limits<AdjEdgeIdx>::max();
}
- NodeEntry(VectorPtr Costs) : Costs(Costs) {}
+ NodeEntry(VectorPtr Costs) : Costs(std::move(Costs)) {}
AdjEdgeIdx addAdjEdgeId(EdgeId EId) {
AdjEdgeIdx Idx = AdjEdgeIds.size();
@@ -103,7 +102,7 @@ namespace PBQP {
class EdgeEntry {
public:
EdgeEntry(NodeId N1Id, NodeId N2Id, MatrixPtr Costs)
- : Costs(Costs) {
+ : Costs(std::move(Costs)) {
NIds[0] = N1Id;
NIds[1] = N2Id;
ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx();
@@ -348,7 +347,8 @@ namespace PBQP {
Graph() : Solver(nullptr) {}
/// @brief Construct an empty PBQP graph with the given graph metadata.
- Graph(GraphMetadata Metadata) : Metadata(Metadata), Solver(nullptr) {}
+ Graph(GraphMetadata Metadata)
+ : Metadata(std::move(Metadata)), Solver(nullptr) {}
/// @brief Get a reference to the graph metadata.
GraphMetadata& getMetadata() { return Metadata; }
diff --git a/include/llvm/CodeGen/ParallelCG.h b/include/llvm/CodeGen/ParallelCG.h
index fa7002fa21fb4..14ef0ec408ba1 100644
--- a/include/llvm/CodeGen/ParallelCG.h
+++ b/include/llvm/CodeGen/ParallelCG.h
@@ -14,29 +14,34 @@
#ifndef LLVM_CODEGEN_PARALLELCG_H
#define LLVM_CODEGEN_PARALLELCG_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetMachine.h"
+#include <functional>
+
namespace llvm {
+template <typename T> class ArrayRef;
class Module;
class TargetOptions;
class raw_pwrite_stream;
-/// Split M into OSs.size() partitions, and generate code for each. Writes
-/// OSs.size() output files to the output streams in OSs. The resulting output
-/// files if linked together are intended to be equivalent to the single output
-/// file that would have been code generated from M.
+/// Split M into OSs.size() partitions, and generate code for each. Takes a
+/// factory function for the TargetMachine TMFactory. Writes OSs.size() output
+/// files to the output streams in OSs. The resulting output files if linked
+/// together are intended to be equivalent to the single output file that would
+/// have been code generated from M.
+///
+/// Writes bitcode for individual partitions into output streams in BCOSs, if
+/// BCOSs is not empty.
///
/// \returns M if OSs.size() == 1, otherwise returns std::unique_ptr<Module>().
std::unique_ptr<Module>
splitCodeGen(std::unique_ptr<Module> M, ArrayRef<raw_pwrite_stream *> OSs,
- StringRef CPU, StringRef Features, const TargetOptions &Options,
- Reloc::Model RM = Reloc::Default,
- CodeModel::Model CM = CodeModel::Default,
- CodeGenOpt::Level OL = CodeGenOpt::Default,
- TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile);
+ ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
+ const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
+ TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile,
+ bool PreserveLocals = false);
} // namespace llvm
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index f45f0ed57d6b6..ae9e5dfe2d65e 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -15,352 +15,21 @@
#ifndef LLVM_CODEGEN_PASSES_H
#define LLVM_CODEGEN_PASSES_H
-#include "llvm/Pass.h"
-#include "llvm/Target/TargetMachine.h"
#include <functional>
#include <string>
namespace llvm {
+class Function;
+class FunctionPass;
class MachineFunctionPass;
-class PassConfigImpl;
-class PassInfo;
-class ScheduleDAGInstrs;
-class TargetLowering;
-class TargetLoweringBase;
+class ModulePass;
+class Pass;
+class TargetMachine;
class TargetRegisterClass;
class raw_ostream;
-struct MachineSchedContext;
-
-// The old pass manager infrastructure is hidden in a legacy namespace now.
-namespace legacy {
-class PassManagerBase;
-}
-using legacy::PassManagerBase;
-
-/// Discriminated union of Pass ID types.
-///
-/// The PassConfig API prefers dealing with IDs because they are safer and more
-/// efficient. IDs decouple configuration from instantiation. This way, when a
-/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to
-/// refer to a Pass pointer after adding it to a pass manager, which deletes
-/// redundant pass instances.
-///
-/// However, it is convient to directly instantiate target passes with
-/// non-default ctors. These often don't have a registered PassInfo. Rather than
-/// force all target passes to implement the pass registry boilerplate, allow
-/// the PassConfig API to handle either type.
-///
-/// AnalysisID is sadly char*, so PointerIntPair won't work.
-class IdentifyingPassPtr {
- union {
- AnalysisID ID;
- Pass *P;
- };
- bool IsInstance;
-public:
- IdentifyingPassPtr() : P(nullptr), IsInstance(false) {}
- IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {}
- IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {}
-
- bool isValid() const { return P; }
- bool isInstance() const { return IsInstance; }
-
- AnalysisID getID() const {
- assert(!IsInstance && "Not a Pass ID");
- return ID;
- }
- Pass *getInstance() const {
- assert(IsInstance && "Not a Pass Instance");
- return P;
- }
-};
-
-template <> struct isPodLike<IdentifyingPassPtr> {
- static const bool value = true;
-};
-
-/// Target-Independent Code Generator Pass Configuration Options.
-///
-/// This is an ImmutablePass solely for the purpose of exposing CodeGen options
-/// to the internals of other CodeGen passes.
-class TargetPassConfig : public ImmutablePass {
-public:
- /// Pseudo Pass IDs. These are defined within TargetPassConfig because they
- /// are unregistered pass IDs. They are only useful for use with
- /// TargetPassConfig APIs to identify multiple occurrences of the same pass.
- ///
-
- /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early
- /// during codegen, on SSA form.
- static char EarlyTailDuplicateID;
-
- /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine
- /// optimization after regalloc.
- static char PostRAMachineLICMID;
-
-private:
- PassManagerBase *PM;
- AnalysisID StartBefore, StartAfter;
- AnalysisID StopAfter;
- bool Started;
- bool Stopped;
- bool AddingMachinePasses;
-
-protected:
- TargetMachine *TM;
- PassConfigImpl *Impl; // Internal data structures
- bool Initialized; // Flagged after all passes are configured.
-
- // Target Pass Options
- // Targets provide a default setting, user flags override.
- //
- bool DisableVerify;
-
- /// Default setting for -enable-tail-merge on this target.
- bool EnableTailMerge;
-
-public:
- TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
- // Dummy constructor.
- TargetPassConfig();
-
- ~TargetPassConfig() override;
-
- static char ID;
-
- /// Get the right type of TargetMachine for this target.
- template<typename TMC> TMC &getTM() const {
- return *static_cast<TMC*>(TM);
- }
-
- //
- void setInitialized() { Initialized = true; }
-
- CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); }
-
- /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
- /// a portion of the normal code-gen pass sequence.
- ///
- /// If the StartAfter and StartBefore pass ID is zero, then compilation will
- /// begin at the normal point; otherwise, clear the Started flag to indicate
- /// that passes should not be added until the starting pass is seen. If the
- /// Stop pass ID is zero, then compilation will continue to the end.
- ///
- /// This function expects that at least one of the StartAfter or the
- /// StartBefore pass IDs is null.
- void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter,
- AnalysisID StopAfter) {
- if (StartAfter)
- assert(!StartBefore && "Start after and start before passes are given");
- this->StartBefore = StartBefore;
- this->StartAfter = StartAfter;
- this->StopAfter = StopAfter;
- Started = (StartAfter == nullptr) && (StartBefore == nullptr);
- }
-
- void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
- bool getEnableTailMerge() const { return EnableTailMerge; }
- void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, 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.
- void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID);
-
- /// Insert InsertedPassID pass after TargetPassID pass.
- void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID,
- bool VerifyAfter = true, bool PrintAfter = true);
-
- /// Allow the target to enable a specific standard pass by default.
- void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); }
-
- /// Allow the target to disable a specific standard pass by default.
- void disablePass(AnalysisID PassID) {
- substitutePass(PassID, IdentifyingPassPtr());
- }
-
- /// Return the pass substituted for StandardID by the target.
- /// If no substitution exists, return StandardID.
- IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const;
-
- /// Return true if the optimized regalloc pipeline is enabled.
- bool getOptimizeRegAlloc() const;
-
- /// Return true if shrink wrapping is enabled.
- bool getEnableShrinkWrap() const;
-
- /// Return true if the default global register allocator is in use and
- /// has not be overriden on the command line with '-regalloc=...'
- bool usingDefaultRegAlloc() const;
-
- /// Add common target configurable passes that perform LLVM IR to IR
- /// transforms following machine independent optimization.
- virtual void addIRPasses();
-
- /// Add passes to lower exception handling for the code generator.
- void addPassesToHandleExceptions();
-
- /// Add pass to prepare the LLVM IR for code generation. This should be done
- /// before exception handling preparation passes.
- virtual void addCodeGenPrepare();
-
- /// Add common passes that perform LLVM IR to IR transforms in preparation for
- /// instruction selection.
- virtual void addISelPrepare();
-
- /// addInstSelector - This method should install an instruction selector pass,
- /// which converts from LLVM code to machine instructions.
- virtual bool addInstSelector() {
- return true;
- }
-
- /// Add the complete, standard set of LLVM CodeGen passes.
- /// Fully developed targets will not generally override this.
- virtual void addMachinePasses();
-
- /// Create an instance of ScheduleDAGInstrs to be run within the standard
- /// MachineScheduler pass for this function and target at the current
- /// optimization level.
- ///
- /// This can also be used to plug a new MachineSchedStrategy into an instance
- /// of the standard ScheduleDAGMI:
- /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /*RemoveKillFlags=*/false)
- ///
- /// Return NULL to select the default (generic) machine scheduler.
- virtual ScheduleDAGInstrs *
- createMachineScheduler(MachineSchedContext *C) const {
- return nullptr;
- }
-
- /// Similar to createMachineScheduler but used when postRA machine scheduling
- /// is enabled.
- virtual ScheduleDAGInstrs *
- createPostMachineScheduler(MachineSchedContext *C) const {
- return nullptr;
- }
-
-protected:
- // Helper to verify the analysis is really immutable.
- void setOpt(bool &Opt, bool Val);
-
- /// Methods with trivial inline returns are convenient points in the common
- /// codegen pass pipeline where targets may insert passes. Methods with
- /// out-of-line standard implementations are major CodeGen stages called by
- /// addMachinePasses. Some targets may override major stages when inserting
- /// passes is insufficient, but maintaining overriden stages is more work.
- ///
-
- /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM
- /// passes (which are run just before instruction selector).
- virtual bool addPreISel() {
- return true;
- }
-
- /// addMachineSSAOptimization - Add standard passes that optimize machine
- /// instructions in SSA form.
- virtual void addMachineSSAOptimization();
-
- /// Add passes that optimize instruction level parallelism for out-of-order
- /// targets. These passes are run while the machine code is still in SSA
- /// form, so they can use MachineTraceMetrics to control their heuristics.
- ///
- /// All passes added here should preserve the MachineDominatorTree,
- /// MachineLoopInfo, and MachineTraceMetrics analyses.
- virtual bool addILPOpts() {
- return false;
- }
-
- /// This method may be implemented by targets that want to run passes
- /// immediately before register allocation.
- virtual void addPreRegAlloc() { }
-
- /// createTargetRegisterAllocator - Create the register allocator pass for
- /// this target at the current optimization level.
- virtual FunctionPass *createTargetRegisterAllocator(bool Optimized);
-
- /// addFastRegAlloc - Add the minimum set of target-independent passes that
- /// are required for fast register allocation.
- virtual void addFastRegAlloc(FunctionPass *RegAllocPass);
-
- /// addOptimizedRegAlloc - Add passes related to register allocation.
- /// LLVMTargetMachine provides standard regalloc passes for most targets.
- virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass);
-
- /// addPreRewrite - Add passes to the optimized register allocation pipeline
- /// after register allocation is complete, but before virtual registers are
- /// rewritten to physical registers.
- ///
- /// These passes must preserve VirtRegMap and LiveIntervals, and when running
- /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix.
- /// When these passes run, VirtRegMap contains legal physreg assignments for
- /// all virtual registers.
- virtual bool addPreRewrite() {
- return false;
- }
-
- /// This method may be implemented by targets that want to run passes after
- /// register allocation pass pipeline but before prolog-epilog insertion.
- virtual void addPostRegAlloc() { }
-
- /// Add passes that optimize machine instructions after register allocation.
- virtual void addMachineLateOptimization();
-
- /// This method may be implemented by targets that want to run passes after
- /// prolog-epilog insertion and before the second instruction scheduling pass.
- virtual void addPreSched2() { }
-
- /// addGCPasses - Add late codegen passes that analyze code for garbage
- /// collection. This should return true if GC info should be printed after
- /// these passes.
- virtual bool addGCPasses();
-
- /// Add standard basic block placement passes.
- virtual void addBlockPlacement();
-
- /// This pass may be implemented by targets that want to run passes
- /// immediately before machine code is emitted.
- virtual void addPreEmitPass() { }
-
- /// Utilities for targets to add passes to the pass manager.
- ///
-
- /// Add a CodeGen pass at this point in the pipeline after checking overrides.
- /// Return the pass that was added, or zero if no pass was added.
- /// @p printAfter if true and adding a machine function pass add an extra
- /// machine printer pass afterwards
- /// @p verifyAfter if true and adding a machine function pass add an extra
- /// machine verification pass afterwards.
- AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true,
- bool printAfter = true);
-
- /// Add a pass to the PassManager if that pass is supposed to be run, as
- /// determined by the StartAfter and StopAfter options. Takes ownership of the
- /// pass.
- /// @p printAfter if true and adding a machine function pass add an extra
- /// machine printer pass afterwards
- /// @p verifyAfter if true and adding a machine function pass add an extra
- /// machine verification pass afterwards.
- void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true);
-
- /// addMachinePasses helper to create the target-selected or overriden
- /// regalloc pass.
- FunctionPass *createRegAllocPass(bool Optimized);
-
- /// printAndVerify - Add a pass to dump then verify the machine function, if
- /// those steps are enabled.
- ///
- void printAndVerify(const std::string &Banner);
-
- /// Add a pass to print the machine function if printing is enabled.
- void addPrintPass(const std::string &Banner);
-
- /// Add a pass to perform basic verification of the machine function if
- /// verification is enabled.
- void addVerifyPass(const std::string &Banner);
-};
-} // namespace llvm
+} // End llvm namespace
/// List of target independent CodeGen pass IDs.
namespace llvm {
@@ -457,6 +126,9 @@ namespace llvm {
/// DeadMachineInstructionElim - This pass removes dead machine instructions.
extern char &DeadMachineInstructionElimID;
+ /// This pass adds dead/undef flags after analyzing subregister lanes.
+ extern char &DetectDeadLanesID;
+
/// FastRegisterAllocation Pass - This pass register allocates as fast as
/// possible. It is best suited for debug code where live ranges are short.
///
@@ -480,11 +152,16 @@ namespace llvm {
/// PrologEpilogCodeInserter - This pass inserts prolog and epilog code,
/// and eliminates abstract frame references.
extern char &PrologEpilogCodeInserterID;
+ MachineFunctionPass *createPrologEpilogInserterPass(const TargetMachine *TM);
/// ExpandPostRAPseudos - This pass expands pseudo instructions after
/// register allocation.
extern char &ExpandPostRAPseudosID;
+ /// createPostRAHazardRecognizer - This pass runs the post-ra hazard
+ /// recognizer.
+ extern char &PostRAHazardRecognizerID;
+
/// createPostRAScheduler - This pass performs post register allocation
/// scheduling.
extern char &PostRASchedulerID;
@@ -586,6 +263,13 @@ namespace llvm {
/// \brief This pass lays out funclets contiguously.
extern char &FuncletLayoutID;
+ /// This pass inserts the XRay instrumentation sleds if they are supported by
+ /// the target platform.
+ extern char &XRayInstrumentationID;
+
+ /// \brief This pass implements the "patchable-function" attribute.
+ extern char &PatchableFunctionID;
+
/// createStackProtectorPass - This pass adds stack protectors to functions.
///
FunctionPass *createStackProtectorPass(const TargetMachine *TM);
@@ -654,6 +338,42 @@ namespace llvm {
/// memory accesses to target specific intrinsics.
///
FunctionPass *createInterleavedAccessPass(const TargetMachine *TM);
+
+ /// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all
+ /// TLS variables for the emulated TLS model.
+ ///
+ ModulePass *createLowerEmuTLSPass(const TargetMachine *TM);
+
+ /// This pass lowers the @llvm.load.relative intrinsic to instructions.
+ /// This is unsafe to do earlier because a pass may combine the constant
+ /// initializer into the load, which may result in an overflowing evaluation.
+ ModulePass *createPreISelIntrinsicLoweringPass();
+
+ /// GlobalMerge - This pass merges internal (by default) globals into structs
+ /// to enable reuse of a base pointer by indexed addressing modes.
+ /// It can also be configured to focus on size optimizations only.
+ ///
+ Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset,
+ bool OnlyOptimizeForSize = false,
+ bool MergeExternalByDefault = false);
+
+ /// This pass splits the stack into a safe stack and an unsafe stack to
+ /// protect against stack-based overflow vulnerabilities.
+ FunctionPass *createSafeStackPass(const TargetMachine *TM = nullptr);
+
+ /// This pass detects subregister lanes in a virtual register that are used
+ /// independently of other lanes and splits them into separate virtual
+ /// registers.
+ extern char &RenameIndependentSubregsID;
+
+ /// This pass is executed POST-RA to collect which physical registers are
+ /// preserved by given machine function.
+ FunctionPass *createRegUsageInfoCollector();
+
+ /// Return a MachineFunction pass that identifies call sites
+ /// and propagates register usage information of callee to caller
+ /// if available with PysicalRegisterUsageInfo pass.
+ FunctionPass *createRegUsageInfoPropPass();
} // End llvm namespace
/// Target machine pass initializer for passes with dependencies. Use with
@@ -662,15 +382,18 @@ namespace llvm {
/// Target machine pass initializer for passes with dependencies. Use with
/// INITIALIZE_TM_PASS_BEGIN.
-#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \
- PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
- PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \
- PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \
- Registry.registerPass(*PI, true); \
- return PI; \
- } \
- void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
+#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \
+ PassInfo *PI = new PassInfo( \
+ name, arg, &passName::ID, \
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis, \
+ PassInfo::TargetMachineCtor_t(callTargetMachineCtor<passName>)); \
+ Registry.registerPass(*PI, true); \
+ return PI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##passName##PassFlag, \
+ initialize##passName##PassOnce, std::ref(Registry)); \
}
/// This initializer registers TargetMachine constructor, so the pass being
@@ -678,8 +401,8 @@ namespace llvm {
/// macro to be together with INITIALIZE_PASS, which is a complete target
/// independent initializer, and we don't want to make libScalarOpts depend
/// on libCodeGen.
-#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
- INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \
- INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis)
+#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
+ INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \
+ INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis)
#endif
diff --git a/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/include/llvm/CodeGen/PreISelIntrinsicLowering.h
new file mode 100644
index 0000000000000..765ca085244aa
--- /dev/null
+++ b/include/llvm/CodeGen/PreISelIntrinsicLowering.h
@@ -0,0 +1,26 @@
+//===--- PreISelIntrinsicLowering.h - Pre-ISel intrinsic lowering pass ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass implements IR lowering for the llvm.load.relative intrinsic.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CODEGEN_PREISELINTRINSICLOWERING_H
+#define LLVM_CODEGEN_PREISELINTRINSICLOWERING_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct PreISelIntrinsicLoweringPass
+ : PassInfoMixin<PreISelIntrinsicLoweringPass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_CODEGEN_PREISELINTRINSICLOWERING_H
diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h
index f67552030db4f..c3f6fde9fb3fa 100644
--- a/include/llvm/CodeGen/PseudoSourceValue.h
+++ b/include/llvm/CodeGen/PseudoSourceValue.h
@@ -27,6 +27,8 @@ class MachineMemOperand;
class raw_ostream;
raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MMO);
+class PseudoSourceValue;
+raw_ostream &operator<<(raw_ostream &OS, const PseudoSourceValue* PSV);
/// Special value supplied for machine level alias analysis. It indicates that
/// a memory access references the functions stack frame (e.g., a spill slot),
@@ -45,6 +47,8 @@ public:
private:
PSVKind Kind;
+ friend raw_ostream &llvm::operator<<(raw_ostream &OS,
+ const PseudoSourceValue* PSV);
friend class MachineMemOperand; // For printCustom().
diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h
index 4122811a9e5ce..21952272ffdb9 100644
--- a/include/llvm/CodeGen/RegAllocPBQP.h
+++ b/include/llvm/CodeGen/RegAllocPBQP.h
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/PBQP/ReductionRules.h"
#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/Support/ErrorHandling.h"
+#include <set>
namespace llvm {
diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h
index 9bbdf3e071bd6..aaddac40ca768 100644
--- a/include/llvm/CodeGen/RegisterPressure.h
+++ b/include/llvm/CodeGen/RegisterPressure.h
@@ -26,14 +26,22 @@ class LiveRange;
class RegisterClassInfo;
class MachineInstr;
+struct RegisterMaskPair {
+ unsigned RegUnit; ///< Virtual register or register unit.
+ LaneBitmask LaneMask;
+
+ RegisterMaskPair(unsigned RegUnit, LaneBitmask LaneMask)
+ : RegUnit(RegUnit), LaneMask(LaneMask) {}
+};
+
/// Base class for register pressure results.
struct RegisterPressure {
/// Map of max reg pressure indexed by pressure set ID, not class ID.
std::vector<unsigned> MaxSetPressure;
/// List of live in virtual registers or physical register units.
- SmallVector<unsigned,8> LiveInRegs;
- SmallVector<unsigned,8> LiveOutRegs;
+ SmallVector<RegisterMaskPair,8> LiveInRegs;
+ SmallVector<RegisterMaskPair,8> LiveOutRegs;
void dump(const TargetRegisterInfo *TRI) const;
};
@@ -144,23 +152,32 @@ public:
/// List of registers defined and used by a machine instruction.
class RegisterOperands {
public:
- /// List of virtual regiserts and register units read by the instruction.
- SmallVector<unsigned, 8> Uses;
+ /// List of virtual registers and register units read by the instruction.
+ SmallVector<RegisterMaskPair, 8> Uses;
/// \brief List of virtual registers and register units defined by the
/// instruction which are not dead.
- SmallVector<unsigned, 8> Defs;
+ SmallVector<RegisterMaskPair, 8> Defs;
/// \brief List of virtual registers and register units defined by the
/// instruction but dead.
- SmallVector<unsigned, 8> DeadDefs;
+ SmallVector<RegisterMaskPair, 8> DeadDefs;
/// Analyze the given instruction \p MI and fill in the Uses, Defs and
/// DeadDefs list based on the MachineOperand flags.
void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI,
- const MachineRegisterInfo &MRI, bool IgnoreDead = false);
+ const MachineRegisterInfo &MRI, bool TrackLaneMasks,
+ bool IgnoreDead);
/// Use liveness information to find dead defs not marked with a dead flag
/// and move them to the DeadDefs vector.
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS);
+
+ /// Use liveness information to find out which uses/defs are partially
+ /// undefined/dead and adjust the RegisterMaskPairs accordingly.
+ /// If \p AddFlagsMI is given then missing read-undef and dead flags will be
+ /// added to the instruction.
+ void adjustLaneLiveness(const LiveIntervals &LIS,
+ const MachineRegisterInfo &MRI, SlotIndex Pos,
+ MachineInstr *AddFlagsMI = nullptr);
};
/// Array of PressureDiffs.
@@ -225,7 +242,20 @@ struct RegPressureDelta {
/// and virtual register indexes to an index usable by the sparse set.
class LiveRegSet {
private:
- SparseSet<unsigned> Regs;
+ struct IndexMaskPair {
+ unsigned Index;
+ LaneBitmask LaneMask;
+
+ IndexMaskPair(unsigned Index, LaneBitmask LaneMask)
+ : Index(Index), LaneMask(LaneMask) {}
+
+ unsigned getSparseSetIndex() const {
+ return Index;
+ }
+ };
+
+ typedef SparseSet<IndexMaskPair> RegSet;
+ RegSet Regs;
unsigned NumRegUnits;
unsigned getSparseIndexFromReg(unsigned Reg) const {
@@ -244,19 +274,37 @@ public:
void clear();
void init(const MachineRegisterInfo &MRI);
- bool contains(unsigned Reg) const {
+ LaneBitmask contains(unsigned Reg) const {
unsigned SparseIndex = getSparseIndexFromReg(Reg);
- return Regs.count(SparseIndex);
+ RegSet::const_iterator I = Regs.find(SparseIndex);
+ if (I == Regs.end())
+ return 0;
+ return I->LaneMask;
}
- bool insert(unsigned Reg) {
- unsigned SparseIndex = getSparseIndexFromReg(Reg);
- return Regs.insert(SparseIndex).second;
+ /// Mark the \p Pair.LaneMask lanes of \p Pair.Reg as live.
+ /// Returns the previously live lanes of \p Pair.Reg.
+ LaneBitmask insert(RegisterMaskPair Pair) {
+ unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit);
+ auto InsertRes = Regs.insert(IndexMaskPair(SparseIndex, Pair.LaneMask));
+ if (!InsertRes.second) {
+ unsigned PrevMask = InsertRes.first->LaneMask;
+ InsertRes.first->LaneMask |= Pair.LaneMask;
+ return PrevMask;
+ }
+ return 0;
}
- bool erase(unsigned Reg) {
- unsigned SparseIndex = getSparseIndexFromReg(Reg);
- return Regs.erase(SparseIndex);
+ /// Clears the \p Pair.LaneMask lanes of \p Pair.Reg (mark them as dead).
+ /// Returns the previously live lanes of \p Pair.Reg.
+ LaneBitmask erase(RegisterMaskPair Pair) {
+ unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit);
+ RegSet::iterator I = Regs.find(SparseIndex);
+ if (I == Regs.end())
+ return 0;
+ unsigned PrevMask = I->LaneMask;
+ I->LaneMask &= ~Pair.LaneMask;
+ return PrevMask;
}
size_t size() const {
@@ -265,9 +313,10 @@ public:
template<typename ContainerT>
void appendTo(ContainerT &To) const {
- for (unsigned I : Regs) {
- unsigned Reg = getRegFromSparseIndex(I);
- To.push_back(Reg);
+ for (const IndexMaskPair &P : Regs) {
+ unsigned Reg = getRegFromSparseIndex(P.Index);
+ if (P.LaneMask != 0)
+ To.push_back(RegisterMaskPair(Reg, P.LaneMask));
}
}
};
@@ -308,6 +357,9 @@ class RegPressureTracker {
/// True if UntiedDefs will be populated.
bool TrackUntiedDefs;
+ /// True if lanemasks should be tracked.
+ bool TrackLaneMasks;
+
/// Register pressure corresponds to liveness before this instruction
/// iterator. It may point to the end of the block or a DebugValue rather than
/// an instruction.
@@ -327,23 +379,23 @@ class RegPressureTracker {
public:
RegPressureTracker(IntervalPressure &rp) :
MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp),
- RequireIntervals(true), TrackUntiedDefs(false) {}
+ 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) {}
+ RequireIntervals(false), TrackUntiedDefs(false), TrackLaneMasks(false) {}
void reset();
void init(const MachineFunction *mf, const RegisterClassInfo *rci,
const LiveIntervals *lis, const MachineBasicBlock *mbb,
MachineBasicBlock::const_iterator pos,
- bool ShouldTrackUntiedDefs = false);
+ bool TrackLaneMasks, bool TrackUntiedDefs);
/// Force liveness of virtual registers or physical register
/// units. Particularly useful to initialize the livein/out state of the
/// tracker before the first call to advance/recede.
- void addLiveRegs(ArrayRef<unsigned> Regs);
+ void addLiveRegs(ArrayRef<RegisterMaskPair> Regs);
/// Get the MI position corresponding to this register pressure.
MachineBasicBlock::const_iterator getPos() const { return CurrPos; }
@@ -355,14 +407,14 @@ public:
void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; }
/// Recede across the previous instruction.
- void recede(SmallVectorImpl<unsigned> *LiveUses = nullptr);
+ void recede(SmallVectorImpl<RegisterMaskPair> *LiveUses = nullptr);
/// Recede across the previous instruction.
/// This "low-level" variant assumes that recedeSkipDebugValues() was
/// called previously and takes precomputed RegisterOperands for the
/// instruction.
void recede(const RegisterOperands &RegOpers,
- SmallVectorImpl<unsigned> *LiveUses = nullptr);
+ SmallVectorImpl<RegisterMaskPair> *LiveUses = nullptr);
/// Recede until we find an instruction which is not a DebugValue.
void recedeSkipDebugValues();
@@ -370,6 +422,11 @@ public:
/// Advance across the current instruction.
void advance();
+ /// Advance across the current instruction.
+ /// This is a "low-level" variant of advance() which takes precomputed
+ /// RegisterOperands of the instruction.
+ void advance(const RegisterOperands &RegOpers);
+
/// Finalize the region boundaries and recored live ins and live outs.
void closeRegion();
@@ -469,18 +526,31 @@ public:
void dump() const;
protected:
- void discoverLiveOut(unsigned Reg);
- void discoverLiveIn(unsigned Reg);
+ /// Add Reg to the live out set and increase max pressure.
+ void discoverLiveOut(RegisterMaskPair Pair);
+ /// Add Reg to the live in set and increase max pressure.
+ void discoverLiveIn(RegisterMaskPair Pair);
/// \brief Get the SlotIndex for the first nondebug instruction including or
/// after the current position.
SlotIndex getCurrSlot() const;
- void increaseRegPressure(ArrayRef<unsigned> Regs);
- void decreaseRegPressure(ArrayRef<unsigned> Regs);
+ void increaseRegPressure(unsigned RegUnit, LaneBitmask PreviousMask,
+ LaneBitmask NewMask);
+ void decreaseRegPressure(unsigned RegUnit, LaneBitmask PreviousMask,
+ LaneBitmask NewMask);
+
+ void bumpDeadDefs(ArrayRef<RegisterMaskPair> DeadDefs);
void bumpUpwardPressure(const MachineInstr *MI);
void bumpDownwardPressure(const MachineInstr *MI);
+
+ void discoverLiveInOrOut(RegisterMaskPair Pair,
+ SmallVectorImpl<RegisterMaskPair> &LiveInOrOut);
+
+ LaneBitmask getLastUsedLanes(unsigned RegUnit, SlotIndex Pos) const;
+ LaneBitmask getLiveLanesAt(unsigned RegUnit, SlotIndex Pos) const;
+ LaneBitmask getLiveThroughAt(unsigned RegUnit, SlotIndex Pos) const;
};
void dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 122c78534253e..efe1a3c6d0f78 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -7,10 +7,11 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares the machine register scavenger class. It can provide
-// information such as unused register at any point in a machine basic block.
-// It also provides a mechanism to make registers available by evicting them
-// to spill slots.
+/// \file
+/// This file declares the machine register scavenger class. It can provide
+/// information such as unused register at any point in a machine basic block.
+/// It also provides a mechanism to make registers available by evicting them
+/// to spill slots.
//
//===----------------------------------------------------------------------===//
@@ -71,8 +72,8 @@ public:
RegScavenger()
: MBB(nullptr), NumRegUnits(0), Tracking(false) {}
- /// Start tracking liveness from the begin of the specific basic block.
- void enterBasicBlock(MachineBasicBlock *mbb);
+ /// Start tracking liveness from the begin of basic block \p MBB.
+ void enterBasicBlock(MachineBasicBlock &MBB);
/// Move the internal MBB iterator and update register states.
void forward();
diff --git a/include/llvm/CodeGen/RegisterUsageInfo.h b/include/llvm/CodeGen/RegisterUsageInfo.h
new file mode 100644
index 0000000000000..3f88032cb6385
--- /dev/null
+++ b/include/llvm/CodeGen/RegisterUsageInfo.h
@@ -0,0 +1,75 @@
+//==- RegisterUsageInfo.h - Register Usage Informartion Storage -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+/// This pass is simple immutable pass which keeps RegMasks (calculated based on
+/// actual register allocation) for functions in a module and provides simple
+/// API to query this information.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+#define LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class PhysicalRegisterUsageInfo : public ImmutablePass {
+ virtual void anchor();
+
+public:
+ static char ID;
+
+ PhysicalRegisterUsageInfo() : ImmutablePass(ID) {
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializePhysicalRegisterUsageInfoPass(Registry);
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ /// To set TargetMachine *, which is used to print
+ /// analysis when command line option -print-regusage is used.
+ void setTargetMachine(const TargetMachine *TM_) { TM = TM_; }
+
+ bool doInitialization(Module &M) override;
+
+ bool doFinalization(Module &M) override;
+
+ /// To store RegMask for given Function *.
+ void storeUpdateRegUsageInfo(const Function *FP,
+ std::vector<uint32_t> RegMask);
+
+ /// To query stored RegMask for given Function *, it will return nullptr if
+ /// function is not known.
+ const std::vector<uint32_t> *getRegUsageInfo(const Function *FP);
+
+ void print(raw_ostream &OS, const Module *M = nullptr) const override;
+
+private:
+ /// A Dense map from Function * to RegMask.
+ /// In RegMask 0 means register used (clobbered) by function.
+ /// and 1 means content of register will be preserved around function call.
+ DenseMap<const Function *, std::vector<uint32_t>> RegMasks;
+
+ const TargetMachine *TM;
+};
+}
+
+#endif
diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h
index 0097e0472e5c5..9c8f5f487d382 100644
--- a/include/llvm/CodeGen/ResourcePriorityQueue.h
+++ b/include/llvm/CodeGen/ResourcePriorityQueue.h
@@ -72,7 +72,7 @@ namespace llvm {
/// Heuristics for estimating register pressure.
unsigned ParallelLiveRanges;
- signed HorizontalVerticalBalance;
+ int HorizontalVerticalBalance;
public:
ResourcePriorityQueue(SelectionDAGISel *IS);
@@ -103,14 +103,14 @@ namespace llvm {
/// Single cost function reflecting benefit of scheduling SU
/// in the current cycle.
- signed SUSchedulingCost (SUnit *SU);
+ int SUSchedulingCost (SUnit *SU);
/// InitNumRegDefsLeft - Determine the # of regs defined by this node.
///
void initNumRegDefsLeft(SUnit *SU);
void updateNumRegDefsLeft(SUnit *SU);
- signed regPressureDelta(SUnit *SU, bool RawPressure = false);
- signed rawRegPressureDelta (SUnit *SU, unsigned RCId);
+ int regPressureDelta(SUnit *SU, bool RawPressure = false);
+ int rawRegPressureDelta (SUnit *SU, unsigned RCId);
bool empty() const override { return Queue.empty(); }
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 7db03459f9bf6..16d305c7297f9 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -215,6 +215,8 @@ namespace RTLIB {
FMAX_PPCF128,
// CONVERSION
+ FPEXT_F32_PPCF128,
+ FPEXT_F64_PPCF128,
FPEXT_F64_F128,
FPEXT_F32_F128,
FPEXT_F32_F64,
@@ -296,27 +298,35 @@ namespace RTLIB {
OEQ_F32,
OEQ_F64,
OEQ_F128,
+ OEQ_PPCF128,
UNE_F32,
UNE_F64,
UNE_F128,
+ UNE_PPCF128,
OGE_F32,
OGE_F64,
OGE_F128,
+ OGE_PPCF128,
OLT_F32,
OLT_F64,
OLT_F128,
+ OLT_PPCF128,
OLE_F32,
OLE_F64,
OLE_F128,
+ OLE_PPCF128,
OGT_F32,
OGT_F64,
OGT_F128,
+ OGT_PPCF128,
UO_F32,
UO_F64,
UO_F128,
+ UO_PPCF128,
O_F32,
O_F64,
O_F128,
+ O_PPCF128,
// MEMORY
MEMCPY,
@@ -326,7 +336,11 @@ namespace RTLIB {
// EXCEPTION HANDLING
UNWIND_RESUME,
- // Family ATOMICs
+ // Note: there's two sets of atomics libcalls; see
+ // <http://llvm.org/docs/Atomics.html> for more info on the
+ // difference between them.
+
+ // Atomic '__sync_*' libcalls.
SYNC_VAL_COMPARE_AND_SWAP_1,
SYNC_VAL_COMPARE_AND_SWAP_2,
SYNC_VAL_COMPARE_AND_SWAP_4,
@@ -388,9 +402,77 @@ namespace RTLIB {
SYNC_FETCH_AND_UMIN_8,
SYNC_FETCH_AND_UMIN_16,
+ // Atomic '__atomic_*' libcalls.
+ ATOMIC_LOAD,
+ ATOMIC_LOAD_1,
+ ATOMIC_LOAD_2,
+ ATOMIC_LOAD_4,
+ ATOMIC_LOAD_8,
+ ATOMIC_LOAD_16,
+
+ ATOMIC_STORE,
+ ATOMIC_STORE_1,
+ ATOMIC_STORE_2,
+ ATOMIC_STORE_4,
+ ATOMIC_STORE_8,
+ ATOMIC_STORE_16,
+
+ ATOMIC_EXCHANGE,
+ ATOMIC_EXCHANGE_1,
+ ATOMIC_EXCHANGE_2,
+ ATOMIC_EXCHANGE_4,
+ ATOMIC_EXCHANGE_8,
+ ATOMIC_EXCHANGE_16,
+
+ ATOMIC_COMPARE_EXCHANGE,
+ ATOMIC_COMPARE_EXCHANGE_1,
+ ATOMIC_COMPARE_EXCHANGE_2,
+ ATOMIC_COMPARE_EXCHANGE_4,
+ ATOMIC_COMPARE_EXCHANGE_8,
+ ATOMIC_COMPARE_EXCHANGE_16,
+
+ ATOMIC_FETCH_ADD_1,
+ ATOMIC_FETCH_ADD_2,
+ ATOMIC_FETCH_ADD_4,
+ ATOMIC_FETCH_ADD_8,
+ ATOMIC_FETCH_ADD_16,
+
+ ATOMIC_FETCH_SUB_1,
+ ATOMIC_FETCH_SUB_2,
+ ATOMIC_FETCH_SUB_4,
+ ATOMIC_FETCH_SUB_8,
+ ATOMIC_FETCH_SUB_16,
+
+ ATOMIC_FETCH_AND_1,
+ ATOMIC_FETCH_AND_2,
+ ATOMIC_FETCH_AND_4,
+ ATOMIC_FETCH_AND_8,
+ ATOMIC_FETCH_AND_16,
+
+ ATOMIC_FETCH_OR_1,
+ ATOMIC_FETCH_OR_2,
+ ATOMIC_FETCH_OR_4,
+ ATOMIC_FETCH_OR_8,
+ ATOMIC_FETCH_OR_16,
+
+ ATOMIC_FETCH_XOR_1,
+ ATOMIC_FETCH_XOR_2,
+ ATOMIC_FETCH_XOR_4,
+ ATOMIC_FETCH_XOR_8,
+ ATOMIC_FETCH_XOR_16,
+
+ ATOMIC_FETCH_NAND_1,
+ ATOMIC_FETCH_NAND_2,
+ ATOMIC_FETCH_NAND_4,
+ ATOMIC_FETCH_NAND_8,
+ ATOMIC_FETCH_NAND_16,
+
// Stack Protector Fail.
STACKPROTECTOR_CHECK_FAIL,
+ // Deoptimization.
+ DEOPTIMIZE,
+
UNKNOWN_LIBCALL
};
@@ -420,7 +502,7 @@ namespace RTLIB {
/// Return the SYNC_FETCH_AND_* value for the given opcode and type, or
/// UNKNOWN_LIBCALL if there is none.
- Libcall getATOMIC(unsigned Opc, MVT VT);
+ Libcall getSYNC(unsigned Opc, MVT VT);
}
}
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index bda9dbd51fff7..6469cabd3de1b 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -396,6 +396,17 @@ namespace llvm {
/// 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.
+ bool addPredBarrier(SUnit *SU) {
+ SDep Dep(SU, SDep::Barrier);
+ unsigned TrueMemOrderLatency =
+ ((SU->getInstr()->mayStore() && this->getInstr()->mayLoad()) ? 1 : 0);
+ Dep.setLatency(TrueMemOrderLatency);
+ 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.
diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h
index c574df0949119..12124ecc4b3e3 100644
--- a/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -15,12 +15,14 @@
#ifndef LLVM_CODEGEN_SCHEDULEDAGINSTRS_H
#define LLVM_CODEGEN_SCHEDULEDAGINSTRS_H
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SparseMultiSet.h"
#include "llvm/ADT/SparseSet.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include <list>
namespace llvm {
class MachineFrameInfo;
@@ -84,6 +86,15 @@ namespace llvm {
typedef SparseMultiSet<VReg2SUnitOperIdx, VirtReg2IndexFunctor>
VReg2SUnitOperIdxMultiMap;
+ typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType;
+ struct UnderlyingObject : PointerIntPair<ValueType, 1, bool> {
+ UnderlyingObject(ValueType V, bool MayAlias)
+ : PointerIntPair<ValueType, 1, bool>(V, MayAlias) {}
+ ValueType getValue() const { return getPointer(); }
+ bool mayAlias() const { return getInt(); }
+ };
+ typedef SmallVector<UnderlyingObject, 4> UnderlyingObjectsVector;
+
/// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of
/// MachineInstrs.
class ScheduleDAGInstrs : public ScheduleDAG {
@@ -149,10 +160,66 @@ namespace llvm {
/// Tracks the last instructions in this region using each virtual register.
VReg2SUnitOperIdxMultiMap CurrentVRegUses;
- /// PendingLoads - Remember where unknown loads are after the most recent
- /// unknown store, as we iterate. As with Defs and Uses, this is here
- /// to minimize construction/destruction.
- std::vector<SUnit *> PendingLoads;
+ AliasAnalysis *AAForDep;
+
+ /// Remember a generic side-effecting instruction as we proceed.
+ /// No other SU ever gets scheduled around it (except in the special
+ /// case of a huge region that gets reduced).
+ 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.
+ class Value2SUsMap;
+
+ /// Remove in FIFO order some SUs from huge maps.
+ 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.
+ 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);
+ }
+
+ /// Add 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.
+ 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.
+ 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.
+ void insertBarrierChain(Value2SUsMap &map);
+
+ /// For an unanalyzable memory access, this Value is used in maps.
+ UndefValue *UnknownValue;
/// DbgValues - Remember instruction that precedes DBG_VALUE.
/// These are generated by buildSchedGraph but persist so they can be
@@ -214,6 +281,7 @@ namespace llvm {
void buildSchedGraph(AliasAnalysis *AA,
RegPressureTracker *RPTracker = nullptr,
PressureDiffs *PDiffs = nullptr,
+ LiveIntervals *LIS = nullptr,
bool TrackLaneMasks = false);
/// addSchedBarrierDeps - Add dependencies from instructions in the current
diff --git a/include/llvm/CodeGen/ScheduleDAGMutation.h b/include/llvm/CodeGen/ScheduleDAGMutation.h
new file mode 100644
index 0000000000000..02fe2294815c4
--- /dev/null
+++ b/include/llvm/CodeGen/ScheduleDAGMutation.h
@@ -0,0 +1,31 @@
+//==- ScheduleDAGMutation.h - MachineInstr Scheduling ------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ScheduleDAGMutation class, which represents
+// a target-specific mutation of the dependency graph for scheduling.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_SCHEDULEDAGMUTATION_H
+#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() {}
+
+ virtual void apply(ScheduleDAGInstrs *DAG) = 0;
+ };
+}
+
+#endif
diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h
index 8a40e7212ff6d..214be2794ba37 100644
--- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h
+++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h
@@ -17,6 +17,7 @@
namespace llvm {
+class MachineInstr;
class SUnit;
/// HazardRecognizer - This determines whether or not an instruction can be
@@ -70,6 +71,10 @@ public:
/// emitted, to advance the hazard state.
virtual void EmitInstruction(SUnit *) {}
+ /// This overload will be used when the hazard recognizer is being used
+ /// by a non-scheduling pass, which does not use SUnits.
+ virtual void EmitInstruction(MachineInstr *) {}
+
/// PreEmitNoops - This callback is invoked prior to emitting an instruction.
/// It should return the number of noops to emit prior to the provided
/// instruction.
@@ -79,6 +84,12 @@ public:
return 0;
}
+ /// This overload will be used when the hazard recognizer is being used
+ /// by a non-scheduling pass, which does not use SUnits.
+ virtual unsigned PreEmitNoops(MachineInstr *) {
+ return 0;
+ }
+
/// ShouldPreferAnother - This callback may be invoked if getHazardType
/// returns NoHazard. If, even though there is no hazard, it would be better to
/// schedule another available instruction, this callback should return true.
diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
index ab14c2de32b0b..e0c30fe4d82a6 100644
--- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
+++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
@@ -83,11 +83,9 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
void dump() const;
};
-#ifndef NDEBUG
// Support for tracing ScoreboardHazardRecognizer as a component within
- // another module. Follows the current thread-unsafe model of tracing.
- static const char *DebugType;
-#endif
+ // another module.
+ const char *DebugType;
// Itinerary data for the target.
const InstrItineraryData *ItinData;
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index a21e9ae881a75..29cce873c2f3c 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -23,6 +23,7 @@
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
@@ -37,7 +38,7 @@ class MachineFunction;
class MDNode;
class SDDbgValue;
class TargetLowering;
-class TargetSelectionDAGInfo;
+class SelectionDAGTargetInfo;
class SDVTListNode : public FoldingSetNode {
friend struct FoldingSetTrait<SDVTListNode>;
@@ -178,7 +179,7 @@ void checkForCycles(const SelectionDAG *DAG, bool force = false);
///
class SelectionDAG {
const TargetMachine &TM;
- const TargetSelectionDAGInfo *TSI;
+ const SelectionDAGTargetInfo *TSI;
const TargetLowering *TLI;
MachineFunction *MF;
LLVMContext *Context;
@@ -208,6 +209,7 @@ class SelectionDAG {
/// Pool allocation for machine-opcode SDNode operands.
BumpPtrAllocator OperandAllocator;
+ ArrayRecycler<SDUse> OperandRecycler;
/// Pool allocation for misc. objects that are created once per SelectionDAG.
BumpPtrAllocator Allocator;
@@ -247,6 +249,14 @@ public:
virtual void NodeUpdated(SDNode *N);
};
+ struct DAGNodeDeletedListener : public DAGUpdateListener {
+ std::function<void(SDNode *, SDNode *)> Callback;
+ DAGNodeDeletedListener(SelectionDAG &DAG,
+ std::function<void(SDNode *, SDNode *)> Callback)
+ : DAGUpdateListener(DAG), Callback(Callback) {}
+ void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); }
+ };
+
/// When true, additional steps are taken to
/// ensure that getConstant() and similar functions return DAG nodes that
/// have legal types. This is important after type legalization since
@@ -268,6 +278,36 @@ private:
DenseSet<SDNode *> &visited,
int level, bool &printed);
+ template <typename SDNodeT, typename... ArgTypes>
+ SDNodeT *newSDNode(ArgTypes &&... Args) {
+ return new (NodeAllocator.template Allocate<SDNodeT>())
+ SDNodeT(std::forward<ArgTypes>(Args)...);
+ }
+
+ void createOperands(SDNode *Node, ArrayRef<SDValue> Vals) {
+ assert(!Node->OperandList && "Node already has operands");
+ SDUse *Ops = OperandRecycler.allocate(
+ ArrayRecycler<SDUse>::Capacity::get(Vals.size()), OperandAllocator);
+
+ for (unsigned I = 0; I != Vals.size(); ++I) {
+ Ops[I].setUser(Node);
+ Ops[I].setInitial(Vals[I]);
+ }
+ Node->NumOperands = Vals.size();
+ Node->OperandList = Ops;
+ checkForCycles(Node);
+ }
+
+ void removeOperands(SDNode *Node) {
+ if (!Node->OperandList)
+ return;
+ OperandRecycler.deallocate(
+ ArrayRecycler<SDUse>::Capacity::get(Node->NumOperands),
+ Node->OperandList);
+ Node->NumOperands = 0;
+ Node->OperandList = nullptr;
+ }
+
void operator=(const SelectionDAG&) = delete;
SelectionDAG(const SelectionDAG&) = delete;
@@ -287,7 +327,7 @@ public:
const TargetMachine &getTarget() const { return TM; }
const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); }
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
- const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; }
+ const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
/// Pop up a GraphViz/gv window with the DAG rendered using 'dot'.
@@ -427,45 +467,64 @@ public:
//===--------------------------------------------------------------------===//
// Node creation methods.
//
- SDValue getConstant(uint64_t Val, SDLoc DL, EVT VT, bool isTarget = false,
- bool isOpaque = false);
- SDValue getConstant(const APInt &Val, SDLoc DL, EVT VT, bool isTarget = false,
- bool isOpaque = false);
- SDValue getConstant(const ConstantInt &Val, SDLoc DL, EVT VT,
+
+ /// \brief Create a ConstantSDNode wrapping a constant value.
+ /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR.
+ ///
+ /// If only legal types can be produced, this does the necessary
+ /// transformations (e.g., if the vector element type is illegal).
+ /// @{
+ SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT,
+ bool isTarget = false, bool isOpaque = false);
+ SDValue getConstant(const APInt &Val, const SDLoc &DL, EVT VT,
bool isTarget = false, bool isOpaque = false);
- SDValue getIntPtrConstant(uint64_t Val, SDLoc DL, bool isTarget = false);
- SDValue getTargetConstant(uint64_t Val, SDLoc DL, EVT VT,
+ SDValue getConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT,
+ bool isTarget = false, bool isOpaque = false);
+ SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL,
+ bool isTarget = false);
+ SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT,
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
- SDValue getTargetConstant(const APInt &Val, SDLoc DL, EVT VT,
+ SDValue getTargetConstant(const APInt &Val, const SDLoc &DL, EVT VT,
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
- SDValue getTargetConstant(const ConstantInt &Val, SDLoc DL, EVT VT,
+ SDValue getTargetConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT,
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
- // The forms below that take a double should only be used for simple
- // constants that can be exactly represented in VT. No checks are made.
- SDValue getConstantFP(double Val, SDLoc DL, EVT VT, bool isTarget = false);
- SDValue getConstantFP(const APFloat& Val, SDLoc DL, EVT VT,
+ /// @}
+
+ /// \brief Create a ConstantFPSDNode wrapping a constant value.
+ /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR.
+ ///
+ /// If only legal types can be produced, this does the necessary
+ /// transformations (e.g., if the vector element type is illegal).
+ /// The forms that take a double should only be used for simple constants
+ /// that can be exactly represented in VT. No checks are made.
+ /// @{
+ SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT,
bool isTarget = false);
- SDValue getConstantFP(const ConstantFP &CF, SDLoc DL, EVT VT,
+ SDValue getConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT,
bool isTarget = false);
- SDValue getTargetConstantFP(double Val, SDLoc DL, EVT VT) {
+ SDValue getConstantFP(const ConstantFP &CF, const SDLoc &DL, EVT VT,
+ bool isTarget = false);
+ SDValue getTargetConstantFP(double Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
}
- SDValue getTargetConstantFP(const APFloat& Val, SDLoc DL, EVT VT) {
+ SDValue getTargetConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
}
- SDValue getTargetConstantFP(const ConstantFP &Val, SDLoc DL, EVT VT) {
+ SDValue getTargetConstantFP(const ConstantFP &Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
}
- SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT,
+ /// @}
+
+ SDValue getGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT,
int64_t offset = 0, bool isTargetGA = false,
unsigned char TargetFlags = 0);
- SDValue getTargetGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT,
+ SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT,
int64_t offset = 0,
unsigned char TargetFlags = 0) {
return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags);
@@ -502,7 +561,7 @@ public:
SDValue getBasicBlock(MachineBasicBlock *MBB);
SDValue getBasicBlock(MachineBasicBlock *MBB, SDLoc dl);
SDValue getExternalSymbol(const char *Sym, EVT VT);
- SDValue getExternalSymbol(const char *Sym, SDLoc dl, EVT VT);
+ SDValue getExternalSymbol(const char *Sym, const SDLoc &dl, EVT VT);
SDValue getTargetExternalSymbol(const char *Sym, EVT VT,
unsigned char TargetFlags = 0);
SDValue getMCSymbol(MCSymbol *Sym, EVT VT);
@@ -510,7 +569,7 @@ public:
SDValue getValueType(EVT);
SDValue getRegister(unsigned Reg, EVT VT);
SDValue getRegisterMask(const uint32_t *RegMask);
- SDValue getEHLabel(SDLoc dl, SDValue Root, MCSymbol *Label);
+ SDValue getEHLabel(const SDLoc &dl, SDValue Root, MCSymbol *Label);
SDValue getBlockAddress(const BlockAddress *BA, EVT VT,
int64_t Offset = 0, bool isTarget = false,
unsigned char TargetFlags = 0);
@@ -520,7 +579,8 @@ public:
return getBlockAddress(BA, VT, Offset, true, TargetFlags);
}
- SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N) {
+ SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg,
+ SDValue N) {
return getNode(ISD::CopyToReg, dl, MVT::Other, Chain,
getRegister(Reg, N.getValueType()), N);
}
@@ -528,7 +588,7 @@ public:
// This version of the getCopyToReg method takes an extra operand, which
// indicates that there is potentially an incoming glue value (if Glue is not
// null) and that there should be a glue result.
- SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N,
+ SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N,
SDValue Glue) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue };
@@ -537,15 +597,15 @@ public:
}
// Similar to last getCopyToReg() except parameter Reg is a SDValue
- SDValue getCopyToReg(SDValue Chain, SDLoc dl, SDValue Reg, SDValue N,
- SDValue Glue) {
+ SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, SDValue Reg, SDValue N,
+ SDValue Glue) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, Reg, N, Glue };
return getNode(ISD::CopyToReg, dl, VTs,
makeArrayRef(Ops, Glue.getNode() ? 4 : 3));
}
- SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT) {
+ SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT) {
SDVTList VTs = getVTList(VT, MVT::Other);
SDValue Ops[] = { Chain, getRegister(Reg, VT) };
return getNode(ISD::CopyFromReg, dl, VTs, Ops);
@@ -554,8 +614,8 @@ public:
// This version of the getCopyFromReg method takes an extra operand, which
// indicates that there is potentially an incoming glue value (if Glue is not
// null) and that there should be a glue result.
- SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT,
- SDValue Glue) {
+ SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT,
+ SDValue Glue) {
SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue };
return getNode(ISD::CopyFromReg, dl, VTs,
@@ -566,20 +626,46 @@ public:
/// Returns the ConvertRndSat Note: Avoid using this node because it may
/// disappear in the future and most targets don't support it.
- SDValue getConvertRndSat(EVT VT, SDLoc dl, SDValue Val, SDValue DTy,
- SDValue STy,
- SDValue Rnd, SDValue Sat, ISD::CvtCode Code);
+ SDValue getConvertRndSat(EVT VT, const SDLoc &dl, SDValue Val, SDValue DTy,
+ SDValue STy, SDValue Rnd, SDValue Sat,
+ ISD::CvtCode Code);
/// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT,
/// which must be a vector type, must match the number of mask elements
/// NumElts. An integer mask element equal to -1 is treated as undefined.
- SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2,
- const int *MaskElts);
- SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2,
- ArrayRef<int> MaskElts) {
- assert(VT.getVectorNumElements() == MaskElts.size() &&
- "Must have the same number of vector elements as mask elements!");
- return getVectorShuffle(VT, dl, N1, N2, MaskElts.data());
+ SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2,
+ ArrayRef<int> Mask);
+
+ /// Return an ISD::BUILD_VECTOR node. The number of elements in VT,
+ /// which must be a vector type, must match the number of operands in Ops.
+ /// The operands must have the same type as (or, for integers, a type wider
+ /// than) VT's element type.
+ SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef<SDValue> Ops) {
+ // VerifySDNode (via InsertNode) checks BUILD_VECTOR later.
+ return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);
+ }
+
+ /// Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all
+ /// elements. VT must be a vector type. Op's type must be the same as (or,
+ /// for integers, a type wider than) VT's element type.
+ SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op) {
+ // VerifySDNode (via InsertNode) checks BUILD_VECTOR later.
+ if (Op.getOpcode() == ISD::UNDEF) {
+ assert((VT.getVectorElementType() == Op.getValueType() ||
+ (VT.isInteger() &&
+ VT.getVectorElementType().bitsLE(Op.getValueType()))) &&
+ "A splatted value must have a width equal or (for integers) "
+ "greater than the vector element type!");
+ return getNode(ISD::UNDEF, SDLoc(), VT);
+ }
+
+ SmallVector<SDValue, 16> Ops(VT.getVectorNumElements(), Op);
+ return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);
+ }
+
+ /// Return a splat ISD::BUILD_VECTOR node, but with Op's SDLoc.
+ SDValue getSplatBuildVector(EVT VT, SDValue Op) {
+ return getSplatBuildVector(VT, SDLoc(Op), Op);
}
/// \brief Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to
@@ -590,52 +676,52 @@ public:
/// Convert Op, which must be of integer type, to the
/// integer type VT, by either any-extending or truncating it.
- SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);
/// Convert Op, which must be of integer type, to the
/// integer type VT, by either sign-extending or truncating it.
- SDValue getSExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);
/// Convert Op, which must be of integer type, to the
/// integer type VT, by either zero-extending or truncating it.
- SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);
/// Return the expression required to zero extend the Op
/// value assuming it was the smaller SrcTy value.
- SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy);
+ SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT SrcTy);
/// Return an operation which will any-extend the low lanes of the operand
/// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by any-extending the low four
/// lanes of the operand from i8 to i32.
- SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getAnyExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Return an operation which will sign extend the low lanes of the operand
/// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by sign extending the low four
/// lanes of the operand from i8 to i32.
- SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getSignExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Return an operation which will zero extend the low lanes of the operand
/// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by zero extending the low four
/// lanes of the operand from i8 to i32.
- SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getZeroExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Convert Op, which must be of integer type, to the integer type VT,
/// by using an extension appropriate for the target's
/// BooleanContent for type OpVT or truncating it.
- SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT);
+ SDValue getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT);
/// Create a bitwise NOT operation as (XOR Val, -1).
- SDValue getNOT(SDLoc DL, SDValue Val, EVT VT);
+ SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT);
/// \brief Create a logical NOT operation as (XOR Val, BooleanOne).
- SDValue getLogicalNOT(SDLoc DL, SDValue Val, EVT VT);
+ SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT);
/// Return a new CALLSEQ_START node, which always must have a glue result
/// (to ensure it's not CSE'd). CALLSEQ_START does not have a useful SDLoc.
- SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) {
+ SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, const SDLoc &DL) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, Op };
return getNode(ISD::CALLSEQ_START, DL, VTs, Ops);
@@ -645,7 +731,7 @@ public:
/// glue result (to ensure it's not CSE'd).
/// CALLSEQ_END does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2,
- SDValue InGlue, SDLoc DL) {
+ SDValue InGlue, const SDLoc &DL) {
SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue);
SmallVector<SDValue, 4> Ops;
Ops.push_back(Chain);
@@ -668,38 +754,38 @@ public:
/// Gets or creates the specified node.
///
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
ArrayRef<SDUse> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
ArrayRef<SDValue> Ops, const SDNodeFlags *Flags = nullptr);
- SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef<EVT> ResultTys,
ArrayRef<SDValue> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs,
ArrayRef<SDValue> Ops);
// Specialize based on number of operands.
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- const SDNodeFlags *Flags = nullptr);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- SDValue N3);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- SDValue N3, SDValue N4);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- SDValue N3, SDValue N4, SDValue N5);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
+ SDValue N2, const SDNodeFlags *Flags = nullptr);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
+ SDValue N2, SDValue N3);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
+ SDValue N2, SDValue N3, SDValue N4);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
+ SDValue N2, SDValue N3, SDValue N4, SDValue N5);
// Specialize again based on number of operands for nodes with a VTList
// rather than a single VT.
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2, SDValue N3);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2, SDValue N3, SDValue N4);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2, SDValue N3, SDValue N4, SDValue N5);
/// Compute a TokenFactor to force all the incoming stack arguments to be
@@ -707,24 +793,24 @@ public:
/// stack arguments from being clobbered.
SDValue getStackArgumentTokenFactor(SDValue Chain);
- SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
+ SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool AlwaysInline,
bool isTailCall, MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo);
- SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
+ SDValue getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo);
- SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
+ SDValue getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo);
/// Helper function to make it easier to build SetCC's if you just
/// have an ISD::CondCode instead of an SDValue.
///
- SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS,
+ SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS,
ISD::CondCode Cond) {
assert(LHS.getValueType().isVector() == RHS.getValueType().isVector() &&
"Cannot compare scalars to vectors");
@@ -737,8 +823,8 @@ public:
/// Helper function to make it easier to build Select's if you just
/// have operands and don't want to check for vector.
- SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond,
- SDValue LHS, SDValue RHS) {
+ SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS,
+ SDValue RHS) {
assert(LHS.getValueType() == RHS.getValueType() &&
"Cannot use select on differing types");
assert(VT.isVector() == LHS.getValueType().isVector() &&
@@ -750,139 +836,145 @@ public:
/// Helper function to make it easier to build SelectCC's if you
/// just have an ISD::CondCode instead of an SDValue.
///
- SDValue getSelectCC(SDLoc DL, SDValue LHS, SDValue RHS,
- SDValue True, SDValue False, ISD::CondCode Cond) {
+ SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True,
+ SDValue False, ISD::CondCode Cond) {
return getNode(ISD::SELECT_CC, DL, True.getValueType(),
LHS, RHS, True, False, getCondCode(Cond));
}
/// VAArg produces a result and token chain, and takes a pointer
/// and a source value as input.
- SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue getVAArg(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
SDValue SV, unsigned Align);
/// Gets a node for an atomic cmpxchg op. There are two
/// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a
/// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded,
/// a success flag (initially i1), and a chain.
- SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs,
- SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
- MachinePointerInfo PtrInfo, unsigned Alignment,
- AtomicOrdering SuccessOrdering,
+ SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTs, SDValue Chain, SDValue Ptr,
+ SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo,
+ unsigned Alignment, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
- SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs,
- SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
- MachineMemOperand *MMO,
+ SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTs, SDValue Chain, SDValue Ptr,
+ SDValue Cmp, SDValue Swp, MachineMemOperand *MMO,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
/// Gets a node for an atomic op, produces result (if relevant)
/// and chain and takes 2 operands.
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value *PtrVal,
unsigned Alignment, AtomicOrdering Ordering,
SynchronizationScope SynchScope);
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, MachineMemOperand *MMO,
- AtomicOrdering Ordering,
- SynchronizationScope SynchScope);
+ AtomicOrdering Ordering, SynchronizationScope SynchScope);
/// Gets a node for an atomic op, produces result and chain and
/// takes 1 operand.
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, EVT VT,
SDValue Chain, SDValue Ptr, MachineMemOperand *MMO,
- AtomicOrdering Ordering,
- SynchronizationScope SynchScope);
+ AtomicOrdering Ordering, SynchronizationScope SynchScope);
/// Gets a node for an atomic op, produces result and chain and takes N
/// operands.
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList,
- ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
- AtomicOrdering SuccessOrdering,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTList, ArrayRef<SDValue> Ops,
+ MachineMemOperand *MMO, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList,
- ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
- AtomicOrdering Ordering, SynchronizationScope SynchScope);
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTList, ArrayRef<SDValue> Ops,
+ MachineMemOperand *MMO, AtomicOrdering Ordering,
+ SynchronizationScope SynchScope);
/// Creates a MemIntrinsicNode that may produce a
/// result and takes a list of operands. Opcode may be INTRINSIC_VOID,
/// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not
/// less than FIRST_TARGET_MEMORY_OPCODE.
- SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
- ArrayRef<SDValue> Ops,
- EVT MemVT, MachinePointerInfo PtrInfo,
- unsigned Align = 0, bool Vol = false,
- bool ReadMem = true, bool WriteMem = true,
- unsigned Size = 0);
+ SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList,
+ ArrayRef<SDValue> Ops, EVT MemVT,
+ MachinePointerInfo PtrInfo, unsigned Align = 0,
+ bool Vol = false, bool ReadMem = true,
+ bool WriteMem = true, unsigned Size = 0);
- SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
- ArrayRef<SDValue> Ops,
- EVT MemVT, MachineMemOperand *MMO);
+ SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList,
+ ArrayRef<SDValue> Ops, EVT MemVT,
+ MachineMemOperand *MMO);
/// Create a MERGE_VALUES node from the given operands.
- SDValue getMergeValues(ArrayRef<SDValue> Ops, SDLoc dl);
+ SDValue getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl);
/// Loads are not normal binary operators: their result type is not
/// determined by their operands, and they produce a value AND a token chain.
///
- SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
- MachinePointerInfo PtrInfo, bool isVolatile,
- bool isNonTemporal, bool isInvariant, unsigned Alignment,
+ /// This function will set the MOLoad flag on MMOFlags, but you can set it if
+ /// you want. The MOStore flag must not be set.
+ SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
+ MachinePointerInfo PtrInfo, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
- SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
MachineMemOperand *MMO);
- SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT,
- SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo,
- EVT MemVT, bool isVolatile,
- bool isNonTemporal, bool isInvariant, unsigned Alignment,
- const AAMDNodes &AAInfo = AAMDNodes());
- SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT,
+ SDValue
+ getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain,
+ SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT,
+ unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes());
+ SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT,
SDValue Chain, SDValue Ptr, EVT MemVT,
MachineMemOperand *MMO);
- SDValue getIndexedLoad(SDValue OrigLoad, SDLoc dl, SDValue Base,
+ SDValue getIndexedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base,
SDValue Offset, ISD::MemIndexedMode AM);
- SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
- EVT VT, SDLoc dl,
- SDValue Chain, SDValue Ptr, SDValue Offset,
- MachinePointerInfo PtrInfo, EVT MemVT,
- bool isVolatile, bool isNonTemporal, bool isInvariant,
- unsigned Alignment, const AAMDNodes &AAInfo = AAMDNodes(),
+ SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT,
+ const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset,
+ MachinePointerInfo PtrInfo, EVT MemVT, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
- SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
- EVT VT, SDLoc dl,
- SDValue Chain, SDValue Ptr, SDValue Offset,
+ SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT,
+ const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset,
EVT MemVT, MachineMemOperand *MMO);
/// Helper function to build ISD::STORE nodes.
- SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
- MachinePointerInfo PtrInfo, bool isVolatile,
- bool isNonTemporal, unsigned Alignment,
- const AAMDNodes &AAInfo = AAMDNodes());
- SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
+ ///
+ /// This function will set the MOStore flag on MMOFlags, but you can set it if
+ /// you want. The MOLoad and MOInvariant flags must not be set.
+ SDValue
+ getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
+ MachinePointerInfo PtrInfo, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes());
+ SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
MachineMemOperand *MMO);
- SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
- MachinePointerInfo PtrInfo, EVT TVT,
- bool isNonTemporal, bool isVolatile,
- unsigned Alignment,
- const AAMDNodes &AAInfo = AAMDNodes());
- SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
- EVT TVT, MachineMemOperand *MMO);
- SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base,
- SDValue Offset, ISD::MemIndexedMode AM);
-
- SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue
+ getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
+ MachinePointerInfo PtrInfo, EVT TVT, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes());
+ SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val,
+ SDValue Ptr, EVT TVT, MachineMemOperand *MMO);
+ SDValue getIndexedStore(SDValue OrigStoe, const SDLoc &dl, SDValue Base,
+ SDValue Offset, ISD::MemIndexedMode AM);
+
+ /// Returns sum of the base pointer and offset.
+ SDValue getMemBasePlusOffset(SDValue Base, unsigned Offset, const SDLoc &DL);
+
+ SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
SDValue Mask, SDValue Src0, EVT MemVT,
MachineMemOperand *MMO, ISD::LoadExtType);
- SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val,
+ SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val,
SDValue Ptr, SDValue Mask, EVT MemVT,
MachineMemOperand *MMO, bool IsTrunc);
- SDValue getMaskedGather(SDVTList VTs, EVT VT, SDLoc dl,
+ SDValue getMaskedGather(SDVTList VTs, EVT VT, const SDLoc &dl,
ArrayRef<SDValue> Ops, MachineMemOperand *MMO);
- SDValue getMaskedScatter(SDVTList VTs, EVT VT, SDLoc dl,
+ SDValue getMaskedScatter(SDVTList VTs, EVT VT, const SDLoc &dl,
ArrayRef<SDValue> Ops, MachineMemOperand *MMO);
/// Construct a node to track a Value* through the backend.
SDValue getSrcValue(const Value *v);
@@ -895,8 +987,8 @@ public:
SDValue getBitcast(EVT VT, SDValue V);
/// Return an AddrSpaceCastSDNode.
- SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr,
- unsigned SrcAS, unsigned DestAS);
+ SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS,
+ unsigned DestAS);
/// Return the specified value casted to
/// the target's desired shift amount type.
@@ -965,45 +1057,46 @@ public:
/// Note that getMachineNode returns the resultant node. If there is already
/// a node of the specified opcode and operands, it returns that node instead
/// of the current one.
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- SDValue Op1);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- SDValue Op1, SDValue Op2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- SDValue Op1, SDValue Op2, SDValue Op3);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
SDValue Op1);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
SDValue Op1, SDValue Op2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
SDValue Op1, SDValue Op2, SDValue Op3);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, SDValue Op1, SDValue Op2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, SDValue Op1, SDValue Op2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, SDValue Op1);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, SDValue Op1, SDValue Op2);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, ArrayRef<SDValue> Ops);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, SDValue Op1, SDValue Op2);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, SDValue Op1, SDValue Op2,
SDValue Op3);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, EVT VT4, ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl,
- ArrayRef<EVT> ResultTys,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, ArrayRef<SDValue> Ops);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, EVT VT4,
ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl,
+ ArrayRef<EVT> ResultTys, ArrayRef<SDValue> Ops);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, SDVTList VTs,
ArrayRef<SDValue> Ops);
/// A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
- SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT,
+ SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT,
SDValue Operand);
/// A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
- SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT,
+ SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT,
SDValue Operand, SDValue Subreg);
/// Get the specified node if it's already available, or else return NULL.
@@ -1012,16 +1105,17 @@ public:
/// Creates a SDDbgValue node.
SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R,
- bool IsIndirect, uint64_t Off, DebugLoc DL,
+ bool IsIndirect, uint64_t Off, const DebugLoc &DL,
unsigned O);
/// Constant
SDDbgValue *getConstantDbgValue(MDNode *Var, MDNode *Expr, const Value *C,
- uint64_t Off, DebugLoc DL, unsigned O);
+ uint64_t Off, const DebugLoc &DL, unsigned O);
/// FrameIndex
SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI,
- uint64_t Off, DebugLoc DL, unsigned O);
+ uint64_t Off, const DebugLoc &DL,
+ unsigned O);
/// Remove the specified node from the system. If any of its
/// operands then becomes dead, remove them as well. Inform UpdateListener
@@ -1129,9 +1223,11 @@ public:
return DbgInfo->getSDDbgValues(SD);
}
- /// Transfer SDDbgValues.
+private:
+ /// Transfer SDDbgValues. Called via ReplaceAllUses{OfValue}?With
void TransferDbgValues(SDValue From, SDValue To);
+public:
/// Return true if there are any SDDbgValue nodes associated
/// with this SelectionDAG.
bool hasDebugValues() const { return !DbgInfo->empty(); }
@@ -1147,29 +1243,32 @@ public:
void dump() const;
- /// Create a stack temporary, suitable for holding the
- /// specified value type. If minAlign is specified, the slot size will have
- /// at least that alignment.
+ /// Create a stack temporary, suitable for holding the specified value type.
+ /// If minAlign is specified, the slot size will have at least that alignment.
SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1);
- /// Create a stack temporary suitable for holding
- /// either of the specified value types.
+ /// Create a stack temporary suitable for holding either of the specified
+ /// value types.
SDValue CreateStackTemporary(EVT VT1, EVT VT2);
- SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue FoldSymbolOffset(unsigned Opcode, EVT VT,
+ const GlobalAddressSDNode *GA,
+ const SDNode *N2);
+
+ SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT,
SDNode *Cst1, SDNode *Cst2);
- SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT,
const ConstantSDNode *Cst1,
const ConstantSDNode *Cst2);
- SDValue FoldConstantVectorArithmetic(unsigned Opcode, SDLoc DL,
- EVT VT, ArrayRef<SDValue> Ops,
+ SDValue FoldConstantVectorArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT,
+ ArrayRef<SDValue> Ops,
const SDNodeFlags *Flags = nullptr);
/// Constant fold a setcc to true or false.
- SDValue FoldSetCC(EVT VT, SDValue N1,
- SDValue N2, ISD::CondCode Cond, SDLoc dl);
+ SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond,
+ const SDLoc &dl);
/// Return true if the sign bit of Op is known to be zero.
/// We use this predicate to simplify operations downstream.
@@ -1188,27 +1287,32 @@ public:
void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne,
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. Targets can
- /// implement the ComputeNumSignBitsForTarget method in the TargetLowering
- /// class to allow target nodes to be understood.
+ /// 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.
+ bool isKnownToBeAPowerOfTwo(SDValue Val) 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. Targets can implement the
+ /// ComputeNumSignBitsForTarget method in the TargetLowering class to allow
+ /// target nodes to be understood.
unsigned ComputeNumSignBits(SDValue Op, 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 equivalence:
+ /// 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
+ /// equivalence:
/// X|Cst == X+Cst iff X&Cst = 0.
bool isBaseWithConstantOffset(SDValue Op) const;
/// Test whether the given SDValue is known to never be NaN.
bool isKnownNeverNaN(SDValue Op) const;
- /// Test whether the given SDValue is known to never be
- /// positive or negative Zero.
+ /// Test whether the given SDValue is known to never be positive or negative
+ /// zero.
bool isKnownNeverZero(SDValue Op) const;
/// Test whether two SDValues are known to compare equal. This
@@ -1228,10 +1332,12 @@ public:
/// vector op and fill the end of the resulting vector with UNDEFS.
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0);
- /// Return true if LD is loading 'Bytes' bytes from a location that is 'Dist'
- /// units away from the location that the 'Base' load is loading from.
- bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base,
- unsigned Bytes, int Dist) const;
+ /// Return true if loads are next to each other and can be
+ /// merged. Check that both are nonvolatile and if LD is loading
+ /// 'Bytes' bytes from a location that is 'Dist' units away from the
+ /// location that the 'Base' load is loading from.
+ bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base,
+ unsigned Bytes, int Dist) const;
/// Infer alignment of a load / store address. Return 0 if
/// it cannot be inferred.
@@ -1265,8 +1371,12 @@ public:
void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args,
unsigned Start = 0, unsigned Count = 0);
+ /// Compute the default alignment value for the given type.
unsigned getEVTAlignment(EVT MemoryVT) const;
+ /// Test whether the given value is a constant int or similar node.
+ SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N);
+
private:
void InsertNode(SDNode *N);
bool RemoveNodeFromCSEMaps(SDNode *N);
@@ -1276,16 +1386,16 @@ private:
void *&InsertPos);
SDNode *FindModifiedNodeSlot(SDNode *N, ArrayRef<SDValue> Ops,
void *&InsertPos);
- SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, SDLoc loc);
+ SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, const SDLoc &loc);
void DeleteNodeNotInCSEMaps(SDNode *N);
void DeallocateNode(SDNode *N);
void allnodes_clear();
- BinarySDNode *GetBinarySDNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- SDValue N1, SDValue N2,
- const SDNodeFlags *Flags = nullptr);
+ SDNode *GetBinarySDNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs,
+ SDValue N1, SDValue N2,
+ const SDNodeFlags *Flags = nullptr);
/// Look up the node specified by ID in CSEMap. If it exists, return it. If
/// not, return the insertion token that will make insertion faster. This
@@ -1296,7 +1406,7 @@ private:
/// Look up the node specified by ID in CSEMap. If it exists, return it. If
/// not, return the insertion token that will make insertion faster. Performs
/// additional processing for constant nodes.
- SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, DebugLoc DL,
+ SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, const SDLoc &DL,
void *&InsertPos);
/// List of non-single value types.
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index a011e4c338c4a..7f4549d3058f4 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -76,8 +76,8 @@ public:
/// right after selection.
virtual void PostprocessISelDAG() {}
- /// Select - Main hook targets implement to select a node.
- virtual SDNode *Select(SDNode *N) = 0;
+ /// Main hook for targets to transform nodes into machine nodes.
+ virtual void Select(SDNode *N) = 0;
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
/// addressing mode, according to the specified constraint. If this does
@@ -111,6 +111,8 @@ public:
OPC_RecordMemRef,
OPC_CaptureGlueInput,
OPC_MoveChild,
+ OPC_MoveChild0, OPC_MoveChild1, OPC_MoveChild2, OPC_MoveChild3,
+ OPC_MoveChild4, OPC_MoveChild5, OPC_MoveChild6, OPC_MoveChild7,
OPC_MoveParent,
OPC_CheckSame,
OPC_CheckChild0Same, OPC_CheckChild1Same,
@@ -140,11 +142,15 @@ public:
OPC_EmitMergeInputChains,
OPC_EmitMergeInputChains1_0,
OPC_EmitMergeInputChains1_1,
+ OPC_EmitMergeInputChains1_2,
OPC_EmitCopyToReg,
OPC_EmitNodeXForm,
OPC_EmitNode,
+ // Space-optimized forms that implicitly encode number of result VTs.
+ OPC_EmitNode0, OPC_EmitNode1, OPC_EmitNode2,
OPC_MorphNodeTo,
- OPC_MarkGlueResults,
+ // Space-optimized forms that implicitly encode number of result VTs.
+ OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2,
OPC_CompleteMatch
};
@@ -196,11 +202,16 @@ protected:
CurDAG->ReplaceAllUsesWith(F, T);
}
+ /// Replace all uses of \c F with \c T, then remove \c F from the DAG.
+ void ReplaceNode(SDNode *F, SDNode *T) {
+ CurDAG->ReplaceAllUsesWith(F, T);
+ CurDAG->RemoveDeadNode(F);
+ }
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.
- void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, SDLoc DL);
-
+ void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
+ const SDLoc &DL);
public:
// Calls to these predicates are generated by tblgen.
@@ -236,9 +247,8 @@ public:
llvm_unreachable("Tblgen should generate this!");
}
- SDNode *SelectCodeCommon(SDNode *NodeToMatch,
- const unsigned char *MatcherTable,
- unsigned TableSize);
+ void SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
+ unsigned TableSize);
/// \brief Return true if complex patterns for this target can mutate the
/// DAG.
@@ -249,10 +259,10 @@ public:
private:
// Calls to these functions are generated by tblgen.
- SDNode *Select_INLINEASM(SDNode *N);
- SDNode *Select_READ_REGISTER(SDNode *N);
- SDNode *Select_WRITE_REGISTER(SDNode *N);
- SDNode *Select_UNDEF(SDNode *N);
+ void Select_INLINEASM(SDNode *N);
+ void Select_READ_REGISTER(SDNode *N);
+ void Select_WRITE_REGISTER(SDNode *N);
+ void Select_UNDEF(SDNode *N);
void CannotYetSelect(SDNode *N);
private:
@@ -294,11 +304,9 @@ private:
/// state machines that start with a OPC_SwitchOpcode node.
std::vector<unsigned> OpcodeOffset;
- void UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain,
- const SmallVectorImpl<SDNode*> &ChainNodesMatched,
- SDValue InputGlue, const SmallVectorImpl<SDNode*> &F,
- bool isMorphNodeTo);
-
+ void UpdateChains(SDNode *NodeToMatch, SDValue InputChain,
+ const SmallVectorImpl<SDNode *> &ChainNodesMatched,
+ bool isMorphNodeTo);
};
}
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 536fc656e8e2e..cfcc4117f93b6 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -44,7 +44,7 @@ class GlobalValue;
class MachineBasicBlock;
class MachineConstantPoolValue;
class SDNode;
-class BinaryWithFlagsSDNode;
+class HandleSDNode;
class Value;
class MCSymbol;
template <typename T> struct DenseMapInfo;
@@ -66,24 +66,28 @@ struct SDVTList {
namespace ISD {
/// Node predicates
- /// Return true if the specified node is a
- /// BUILD_VECTOR where all of the elements are ~0 or undef.
+ /// If N is a BUILD_VECTOR node whose elements are all the same constant or
+ /// undefined, return true and return the constant value in \p SplatValue.
+ bool isConstantSplatVector(const SDNode *N, APInt &SplatValue);
+
+ /// Return true if the specified node is a BUILD_VECTOR where all of the
+ /// elements are ~0 or undef.
bool isBuildVectorAllOnes(const SDNode *N);
- /// Return true if the specified node is a
- /// BUILD_VECTOR where all of the elements are 0 or undef.
+ /// Return true if the specified node is a BUILD_VECTOR where all of the
+ /// elements are 0 or undef.
bool isBuildVectorAllZeros(const SDNode *N);
- /// \brief Return true if the specified node is a BUILD_VECTOR node of
- /// all ConstantSDNode or undef.
+ /// Return true if the specified node is a BUILD_VECTOR node of all
+ /// ConstantSDNode or undef.
bool isBuildVectorOfConstantSDNodes(const SDNode *N);
- /// \brief Return true if the specified node is a BUILD_VECTOR node of
- /// all ConstantFPSDNode or undef.
+ /// Return true if the specified node is a BUILD_VECTOR node of all
+ /// ConstantFPSDNode or undef.
bool isBuildVectorOfConstantFPSDNodes(const SDNode *N);
- /// Return true if the node has at least one operand
- /// and all operands of the specified node are ISD::UNDEF.
+ /// Return true if the node has at least one operand and all operands of the
+ /// specified node are ISD::UNDEF.
bool allOperandsUndef(const SDNode *N);
} // end llvm:ISD namespace
@@ -280,6 +284,8 @@ public:
private:
friend class SelectionDAG;
friend class SDNode;
+ // TODO: unfriend HandleSDNode once we fix its operand handling.
+ friend class HandleSDNode;
void setUser(SDNode *p) { User = p; }
@@ -328,6 +334,7 @@ private:
bool NoInfs : 1;
bool NoSignedZeros : 1;
bool AllowReciprocal : 1;
+ bool VectorReduction : 1;
public:
/// Default constructor turns off all optimization flags.
@@ -340,6 +347,7 @@ public:
NoInfs = false;
NoSignedZeros = false;
AllowReciprocal = false;
+ VectorReduction = false;
}
// These are mutators for each flag.
@@ -351,6 +359,7 @@ public:
void setNoInfs(bool b) { NoInfs = b; }
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
+ void setVectorReduction(bool b) { VectorReduction = b; }
// These are accessors for each flag.
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
@@ -361,6 +370,7 @@ public:
bool hasNoInfs() const { return NoInfs; }
bool hasNoSignedZeros() const { return NoSignedZeros; }
bool hasAllowReciprocal() const { return AllowReciprocal; }
+ bool hasVectorReduction() const { return VectorReduction; }
/// Return a raw encoding of the flags.
/// This function should only be used to add data to the NodeID value.
@@ -390,10 +400,6 @@ private:
/// The operation that this node performs.
int16_t NodeType;
- /// This is true if OperandList was new[]'d. If true,
- /// then they will be delete[]'d when the node is destroyed.
- uint16_t OperandsNeedDelete : 1;
-
/// This tracks whether this node has one or more dbg_value
/// nodes corresponding to it.
uint16_t HasDebugValue : 1;
@@ -402,7 +408,7 @@ protected:
/// This member is defined by this class, but is not used for
/// anything. Subclasses can use it to hold whatever state they find useful.
/// This field is initialized to zero by the ctor.
- uint16_t SubclassData : 14;
+ uint16_t SubclassData : 15;
private:
/// Unique id per SDNode in the DAG.
@@ -436,6 +442,8 @@ private:
friend class SelectionDAG;
friend struct ilist_traits<SDNode>;
+ // TODO: unfriend HandleSDNode once we fix its operand handling.
+ friend class HandleSDNode;
public:
/// Unique and persistent id per SDNode in the DAG.
@@ -621,18 +629,32 @@ public:
/// NOTE: This is an expensive method. Use it carefully.
bool hasPredecessor(const SDNode *N) const;
- /// Return true if N is a predecessor of this node.
- /// N is either an operand of this node, or can be reached by recursively
- /// traversing up the operands.
- /// In this helper the Visited and worklist sets are held externally to
- /// cache predecessors over multiple invocations. If you want to test for
- /// multiple predecessors this method is preferable to multiple calls to
- /// hasPredecessor. Be sure to clear Visited and Worklist if the DAG
- /// changes.
- /// NOTE: This is still very expensive. Use carefully.
- bool hasPredecessorHelper(const SDNode *N,
- SmallPtrSetImpl<const SDNode *> &Visited,
- SmallVectorImpl<const SDNode *> &Worklist) const;
+ /// Returns true if N is a predecessor of any node in Worklist. This
+ /// helper keeps Visited and Worklist sets externally to allow unions
+ /// searches to be performed in parallel, caching of results across
+ /// queries and incremental addition to Worklist. Stops early if N is
+ /// found but will resume. Remember to clear Visited and Worklists
+ /// if DAG changes.
+ static bool hasPredecessorHelper(const SDNode *N,
+ SmallPtrSetImpl<const SDNode *> &Visited,
+ SmallVectorImpl<const SDNode *> &Worklist) {
+ if (Visited.count(N))
+ return true;
+ while (!Worklist.empty()) {
+ const SDNode *M = Worklist.pop_back_val();
+ bool Found = false;
+ for (const SDValue &OpV : M->op_values()) {
+ SDNode *Op = OpV.getNode();
+ if (Visited.insert(Op).second)
+ Worklist.push_back(Op);
+ if (Op == N)
+ Found = true;
+ }
+ if (Found)
+ return true;
+ }
+ return false;
+ }
/// Return the number of values used by this operation.
unsigned getNumOperands() const { return NumOperands; }
@@ -788,101 +810,20 @@ protected:
return Ret;
}
- SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- ArrayRef<SDValue> Ops)
- : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false),
- SubclassData(0), NodeId(-1),
- OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr),
- ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()),
- NumValues(VTs.NumVTs), IROrder(Order), debugLoc(std::move(dl)) {
- assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
- assert(NumOperands == Ops.size() &&
- "NumOperands wasn't wide enough for its operands!");
- assert(NumValues == VTs.NumVTs &&
- "NumValues wasn't wide enough for its operands!");
- for (unsigned i = 0; i != Ops.size(); ++i) {
- assert(OperandList && "no operands available");
- OperandList[i].setUser(this);
- OperandList[i].setInitial(Ops[i]);
- }
- checkForCycles(this);
- }
-
- /// This constructor adds no operands itself; operands can be
- /// set later with InitOperands.
+ /// Create an SDNode.
+ ///
+ /// 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), OperandsNeedDelete(false), HasDebugValue(false),
- SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
- UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs),
- IROrder(Order), debugLoc(std::move(dl)) {
+ : NodeType(Opc), HasDebugValue(false), SubclassData(0), NodeId(-1),
+ OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr),
+ NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order),
+ debugLoc(std::move(dl)) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
"NumValues wasn't wide enough for its operands!");
}
- /// Initialize the operands list of this with 1 operand.
- void InitOperands(SDUse *Ops, const SDValue &Op0) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- NumOperands = 1;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with 2 operands.
- void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- Ops[1].setUser(this);
- Ops[1].setInitial(Op1);
- NumOperands = 2;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with 3 operands.
- void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1,
- const SDValue &Op2) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- Ops[1].setUser(this);
- Ops[1].setInitial(Op1);
- Ops[2].setUser(this);
- Ops[2].setInitial(Op2);
- NumOperands = 3;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with 4 operands.
- void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1,
- const SDValue &Op2, const SDValue &Op3) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- Ops[1].setUser(this);
- Ops[1].setInitial(Op1);
- Ops[2].setUser(this);
- Ops[2].setInitial(Op2);
- Ops[3].setUser(this);
- Ops[3].setInitial(Op3);
- NumOperands = 4;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with N operands.
- void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) {
- for (unsigned i = 0; i != N; ++i) {
- Ops[i].setUser(this);
- Ops[i].setInitial(Vals[i]);
- }
- NumOperands = N;
- assert(NumOperands == N &&
- "NumOperands wasn't wide enough for its operands!");
- OperandList = Ops;
- checkForCycles(this);
- }
-
/// Release the operands and set this node to have zero operands.
void DropOperands();
};
@@ -898,40 +839,20 @@ protected:
/// be used by the DAGBuilder, the other to be used by others.
class SDLoc {
private:
- // Ptr could be used for either Instruction* or SDNode*. It is used for
- // Instruction* if IROrder is not -1.
- const void *Ptr;
- int IROrder;
+ DebugLoc DL;
+ int IROrder = 0;
public:
- SDLoc() : Ptr(nullptr), IROrder(0) {}
- SDLoc(const SDNode *N) : Ptr(N), IROrder(-1) {
- assert(N && "null SDNode");
- }
- SDLoc(const SDValue V) : Ptr(V.getNode()), IROrder(-1) {
- assert(Ptr && "null SDNode");
- }
- SDLoc(const Instruction *I, int Order) : Ptr(I), IROrder(Order) {
+ SDLoc() = default;
+ SDLoc(const SDNode *N) : DL(N->getDebugLoc()), IROrder(N->getIROrder()) {}
+ SDLoc(const SDValue V) : SDLoc(V.getNode()) {}
+ SDLoc(const Instruction *I, int Order) : IROrder(Order) {
assert(Order >= 0 && "bad IROrder");
+ if (I)
+ DL = I->getDebugLoc();
}
- unsigned getIROrder() {
- if (IROrder >= 0 || Ptr == nullptr) {
- return (unsigned)IROrder;
- }
- const SDNode *N = (const SDNode*)(Ptr);
- return N->getIROrder();
- }
- DebugLoc getDebugLoc() {
- if (!Ptr) {
- return DebugLoc();
- }
- if (IROrder >= 0) {
- const Instruction *I = (const Instruction*)(Ptr);
- return I->getDebugLoc();
- }
- const SDNode *N = (const SDNode*)(Ptr);
- return N->getDebugLoc();
- }
+ unsigned getIROrder() const { return IROrder; }
+ const DebugLoc &getDebugLoc() const { return DL; }
};
@@ -1008,30 +929,6 @@ inline void SDUse::setNode(SDNode *N) {
if (N) N->addUse(*this);
}
-/// This class is used for single-operand SDNodes. This is solely
-/// to allow co-allocation of node operands with the node itself.
-class UnarySDNode : public SDNode {
- SDUse Op;
-public:
- UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X)
- : SDNode(Opc, Order, dl, VTs) {
- InitOperands(&Op, X);
- }
-};
-
-/// This class is used for two-operand SDNodes. This is solely
-/// to allow co-allocation of node operands with the node itself.
-class BinarySDNode : public SDNode {
- SDUse Ops[2];
-public:
- BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X, SDValue Y)
- : SDNode(Opc, Order, dl, VTs) {
- InitOperands(Ops, X, Y);
- }
-};
-
/// Returns true if the opcode is a binary operation with flags.
static bool isBinOpWithFlags(unsigned Opcode) {
switch (Opcode) {
@@ -1056,30 +953,17 @@ static bool isBinOpWithFlags(unsigned Opcode) {
/// This class is an extension of BinarySDNode
/// used from those opcodes that have associated extra flags.
-class BinaryWithFlagsSDNode : public BinarySDNode {
+class BinaryWithFlagsSDNode : public SDNode {
public:
SDNodeFlags Flags;
- BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X, SDValue Y, const SDNodeFlags &NodeFlags)
- : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags(NodeFlags) {}
+ BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
+ SDVTList VTs, const SDNodeFlags &NodeFlags)
+ : SDNode(Opc, Order, dl, VTs), Flags(NodeFlags) {}
static bool classof(const SDNode *N) {
return isBinOpWithFlags(N->getOpcode());
}
};
-/// This class is used for three-operand SDNodes. This is solely
-/// to allow co-allocation of node operands with the node itself.
-class TernarySDNode : public SDNode {
- SDUse Ops[3];
-public:
- TernarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X, SDValue Y, SDValue Z)
- : SDNode(Opc, Order, dl, VTs) {
- InitOperands(Ops, X, Y, Z);
- }
-};
-
-
/// This class is used to form a handle around another node that
/// is persistent and is updated across invocations of replaceAllUsesWith on its
/// operand. This node should be directly created by end-users and not added to
@@ -1092,19 +976,27 @@ public:
// HandleSDNodes are never inserted into the DAG, so they won't be
// auto-numbered. Use ID 65535 as a sentinel.
PersistentId = 0xffff;
- InitOperands(&Op, X);
+
+ // Manually set up the operand list. This node type is special in that it's
+ // always stack allocated and SelectionDAG does not manage its operands.
+ // TODO: This should either (a) not be in the SDNode hierarchy, or (b) not
+ // be so special.
+ Op.setUser(this);
+ Op.setInitial(X);
+ NumOperands = 1;
+ OperandList = &Op;
}
~HandleSDNode();
const SDValue &getValue() const { return Op; }
};
-class AddrSpaceCastSDNode : public UnarySDNode {
+class AddrSpaceCastSDNode : public SDNode {
private:
unsigned SrcAddrSpace;
unsigned DestAddrSpace;
public:
- AddrSpaceCastSDNode(unsigned Order, DebugLoc dl, EVT VT, SDValue X,
+ AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl, EVT VT,
unsigned SrcAS, unsigned DestAS);
unsigned getSrcAddressSpace() const { return SrcAddrSpace; }
@@ -1126,12 +1018,9 @@ protected:
MachineMemOperand *MMO;
public:
- MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
+ MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs,
EVT MemoryVT, MachineMemOperand *MMO);
- MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- ArrayRef<SDValue> Ops, EVT MemoryVT, MachineMemOperand *MMO);
-
bool readMem() const { return MMO->isLoad(); }
bool writeMem() const { return MMO->isStore(); }
@@ -1234,8 +1123,6 @@ public:
/// This is an SDNode representing atomic operations.
class AtomicSDNode : public MemSDNode {
- SDUse Ops[4];
-
/// For cmpxchg instructions, the ordering requirements when a store does not
/// occur.
AtomicOrdering FailureOrdering;
@@ -1244,13 +1131,15 @@ class AtomicSDNode : public MemSDNode {
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope) {
// This must match encodeMemSDNodeFlags() in SelectionDAG.cpp.
- assert((SuccessOrdering & 15) == SuccessOrdering &&
+ assert((AtomicOrdering)((unsigned)SuccessOrdering & 15) ==
+ SuccessOrdering &&
"Ordering may not require more than 4 bits!");
- assert((FailureOrdering & 15) == FailureOrdering &&
+ assert((AtomicOrdering)((unsigned)FailureOrdering & 15) ==
+ FailureOrdering &&
"Ordering may not require more than 4 bits!");
assert((SynchScope & 1) == SynchScope &&
"SynchScope may not require more than 1 bit!");
- SubclassData |= SuccessOrdering << 8;
+ SubclassData |= (unsigned)SuccessOrdering << 8;
SubclassData |= SynchScope << 12;
this->FailureOrdering = FailureOrdering;
assert(getSuccessOrdering() == SuccessOrdering &&
@@ -1261,50 +1150,12 @@ class AtomicSDNode : public MemSDNode {
}
public:
- // Opc: opcode for atomic
- // VTL: value type list
- // Chain: memory chain for operaand
- // Ptr: address to update as a SDValue
- // Cmp: compare value
- // Swp: swap value
- // SrcVal: address to update as a Value (used for MemOperand)
- // Align: alignment of memory
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
- EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
- MachineMemOperand *MMO, AtomicOrdering Ordering,
- SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(Ordering, Ordering, SynchScope);
- InitOperands(Ops, Chain, Ptr, Cmp, Swp);
- }
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
- EVT MemVT,
- SDValue Chain, SDValue Ptr,
- SDValue Val, MachineMemOperand *MMO,
- AtomicOrdering Ordering, SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(Ordering, Ordering, SynchScope);
- InitOperands(Ops, Chain, Ptr, Val);
- }
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
- EVT MemVT,
- SDValue Chain, SDValue Ptr,
- MachineMemOperand *MMO,
- AtomicOrdering Ordering, SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(Ordering, Ordering, SynchScope);
- InitOperands(Ops, Chain, Ptr);
- }
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT,
- const SDValue* AllOps, SDUse *DynOps, unsigned NumOps,
- MachineMemOperand *MMO,
+ AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL,
+ EVT MemVT, MachineMemOperand *MMO,
AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
+ : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
InitAtomic(SuccessOrdering, FailureOrdering, SynchScope);
- assert((DynOps || NumOps <= array_lengthof(Ops)) &&
- "Too many ops for internal storage!");
- InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps);
}
const SDValue &getBasePtr() const { return getOperand(1); }
@@ -1351,10 +1202,9 @@ public:
/// with a value not less than FIRST_TARGET_MEMORY_OPCODE.
class MemIntrinsicSDNode : public MemSDNode {
public:
- MemIntrinsicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- ArrayRef<SDValue> Ops, EVT MemoryVT,
- MachineMemOperand *MMO)
- : MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) {
+ MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
+ SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO)
+ : MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) {
SubclassData |= 1u << 13;
}
@@ -1377,20 +1227,15 @@ public:
/// An index of -1 is treated as undef, such that the code generator may put
/// any value in the corresponding element of the result.
class ShuffleVectorSDNode : public SDNode {
- SDUse Ops[2];
-
// The memory for Mask is owned by the SelectionDAG's OperandAllocator, and
// is freed when the SelectionDAG object is destroyed.
const int *Mask;
protected:
friend class SelectionDAG;
- ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1,
- SDValue N2, const int *M)
- : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {
- InitOperands(Ops, N1, N2);
- }
-public:
+ ShuffleVectorSDNode(EVT VT, unsigned Order, const DebugLoc &dl, const int *M)
+ : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {}
+public:
ArrayRef<int> getMask() const {
EVT VT = getValueType(0);
return makeArrayRef(Mask, VT.getVectorNumElements());
@@ -1414,7 +1259,7 @@ public:
/// Change values in a shuffle permute mask assuming
/// the two vector operands have swapped position.
- static void commuteMask(SmallVectorImpl<int> &Mask) {
+ static void commuteMask(MutableArrayRef<int> Mask) {
unsigned NumElems = Mask.size();
for (unsigned i = 0; i != NumElems; ++i) {
int idx = Mask[i];
@@ -1436,9 +1281,10 @@ class ConstantSDNode : public SDNode {
const ConstantInt *Value;
friend class SelectionDAG;
ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
- DebugLoc DL, EVT VT)
- : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant,
- 0, DL, getSDVTList(VT)), Value(val) {
+ const DebugLoc &DL, EVT VT)
+ : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL,
+ getSDVTList(VT)),
+ Value(val) {
SubclassData |= (uint16_t)isOpaque;
}
public:
@@ -1463,10 +1309,12 @@ public:
class ConstantFPSDNode : public SDNode {
const ConstantFP *Value;
friend class SelectionDAG;
- ConstantFPSDNode(bool isTarget, const ConstantFP *val, DebugLoc DL, EVT VT)
- : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP,
- 0, DL, getSDVTList(VT)), Value(val) {
- }
+ ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL,
+ EVT VT)
+ : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL,
+ getSDVTList(VT)),
+ Value(val) {}
+
public:
const APFloat& getValueAPF() const { return Value->getValueAPF(); }
@@ -1517,15 +1365,19 @@ bool isNullFPConstant(SDValue V);
bool isAllOnesConstant(SDValue V);
/// Returns true if \p V is a constant integer one.
bool isOneConstant(SDValue V);
+/// Returns true if \p V is a bitwise not operation. Assumes that an all ones
+/// constant is canonicalized to be operand 1.
+bool isBitwiseNot(SDValue V);
class GlobalAddressSDNode : public SDNode {
const GlobalValue *TheGlobal;
int64_t Offset;
unsigned char TargetFlags;
friend class SelectionDAG;
- GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL,
+ GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL,
const GlobalValue *GA, EVT VT, int64_t o,
unsigned char TargetFlags);
+
public:
const GlobalValue *getGlobal() const { return TheGlobal; }
@@ -1821,13 +1673,11 @@ public:
};
class EHLabelSDNode : public SDNode {
- SDUse Chain;
MCSymbol *Label;
friend class SelectionDAG;
- EHLabelSDNode(unsigned Order, DebugLoc dl, SDValue ch, MCSymbol *L)
- : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {
- InitOperands(&Chain, ch);
- }
+ EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
+ : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {}
+
public:
MCSymbol *getLabel() const { return Label; }
@@ -1892,12 +1742,11 @@ public:
class CvtRndSatSDNode : public SDNode {
ISD::CvtCode CvtCode;
friend class SelectionDAG;
- explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl,
- ArrayRef<SDValue> Ops, ISD::CvtCode Code)
- : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops),
- CvtCode(Code) {
- assert(Ops.size() == 5 && "wrong number of operations");
+ explicit CvtRndSatSDNode(EVT VT, unsigned Order, const DebugLoc &dl,
+ ISD::CvtCode Code)
+ : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT)), CvtCode(Code) {
}
+
public:
ISD::CvtCode getCvtCode() const { return CvtCode; }
@@ -1926,24 +1775,13 @@ public:
/// Base class for LoadSDNode and StoreSDNode
class LSBaseSDNode : public MemSDNode {
- //! Operand array for load and store
- /*!
- \note Moving this array to the base class captures more
- common functionality shared between LoadSDNode and
- StoreSDNode
- */
- SDUse Ops[4];
public:
- LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
- SDValue *Operands, unsigned numOperands,
+ LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl,
SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT,
MachineMemOperand *MMO)
- : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
SubclassData |= AM << 2;
assert(getAddressingMode() == AM && "MemIndexedMode encoding error!");
- InitOperands(Ops, Operands, numOperands);
- assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) &&
- "Only indexed loads and stores have a non-undef offset operand");
}
const SDValue &getOffset() const {
@@ -1971,10 +1809,10 @@ public:
/// This class is used to represent ISD::LOAD nodes.
class LoadSDNode : public LSBaseSDNode {
friend class SelectionDAG;
- LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs,
+ LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT,
MachineMemOperand *MMO)
- : LSBaseSDNode(ISD::LOAD, Order, dl, ChainPtrOff, 3, VTs, AM, MemVT, MMO) {
+ : LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) {
SubclassData |= (unsigned short)ETy;
assert(getExtensionType() == ETy && "LoadExtType encoding error!");
assert(readMem() && "Load MachineMemOperand is not a load!");
@@ -1999,11 +1837,10 @@ public:
/// This class is used to represent ISD::STORE nodes.
class StoreSDNode : public LSBaseSDNode {
friend class SelectionDAG;
- StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl,
- SDVTList VTs, ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
+ StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
MachineMemOperand *MMO)
- : LSBaseSDNode(ISD::STORE, Order, dl, ChainValuePtrOff, 4,
- VTs, AM, MemVT, MMO) {
+ : LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) {
SubclassData |= (unsigned short)isTrunc;
assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!");
assert(!readMem() && "Store MachineMemOperand is a load!");
@@ -2027,16 +1864,12 @@ public:
/// This base class is used to represent MLOAD and MSTORE nodes
class MaskedLoadStoreSDNode : public MemSDNode {
- // Operands
- SDUse Ops[4];
public:
friend class SelectionDAG;
- MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
- SDValue *Operands, unsigned numOperands, SDVTList VTs,
- EVT MemVT, MachineMemOperand *MMO)
- : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
- InitOperands(Ops, Operands, numOperands);
- }
+ MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order,
+ const DebugLoc &dl, SDVTList VTs, EVT MemVT,
+ MachineMemOperand *MMO)
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {}
// In the both nodes address is Op1, mask is Op2:
// MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value
@@ -2055,11 +1888,9 @@ public:
class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
- MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands,
- unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy,
- EVT MemVT, MachineMemOperand *MMO)
- : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands,
- VTs, MemVT, MMO) {
+ MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, MemVT, MMO) {
SubclassData |= (unsigned short)ETy;
}
@@ -2077,12 +1908,10 @@ class MaskedStoreSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
- MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands,
- unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT,
- MachineMemOperand *MMO)
- : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands,
- VTs, MemVT, MMO) {
- SubclassData |= (unsigned short)isTrunc;
+ MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ bool isTrunc, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, MemVT, MMO) {
+ SubclassData |= (unsigned short)isTrunc;
}
/// Return true if the op does a truncation before store.
/// For integers this is the same as doing a TRUNCATE and storing the result.
@@ -2100,17 +1929,12 @@ public:
/// MGATHER and MSCATTER nodes
///
class MaskedGatherScatterSDNode : public MemSDNode {
- // Operands
- SDUse Ops[5];
public:
friend class SelectionDAG;
- MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
- ArrayRef<SDValue> Operands, SDVTList VTs, EVT MemVT,
+ MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order,
+ const DebugLoc &dl, SDVTList VTs, EVT MemVT,
MachineMemOperand *MMO)
- : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
- assert(Operands.size() == 5 && "Incompatible number of operands");
- InitOperands(Ops, Operands.data(), Operands.size());
- }
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {}
// In the both nodes address is Op1, mask is Op2:
// MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value
@@ -2132,19 +1956,9 @@ public:
class MaskedGatherSDNode : public MaskedGatherScatterSDNode {
public:
friend class SelectionDAG;
- MaskedGatherSDNode(unsigned Order, DebugLoc dl, ArrayRef<SDValue> Operands,
- SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
- : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, Operands, VTs, MemVT,
- MMO) {
- assert(getValue().getValueType() == getValueType(0) &&
- "Incompatible type of the PassThru value in MaskedGatherSDNode");
- assert(getMask().getValueType().getVectorNumElements() ==
- getValueType(0).getVectorNumElements() &&
- "Vector width mismatch between mask and data");
- assert(getIndex().getValueType().getVectorNumElements() ==
- getValueType(0).getVectorNumElements() &&
- "Vector width mismatch between index and data");
- }
+ MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ EVT MemVT, MachineMemOperand *MMO)
+ : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO) {}
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MGATHER;
@@ -2157,17 +1971,9 @@ class MaskedScatterSDNode : public MaskedGatherScatterSDNode {
public:
friend class SelectionDAG;
- MaskedScatterSDNode(unsigned Order, DebugLoc dl,ArrayRef<SDValue> Operands,
- SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
- : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, Operands, VTs, MemVT,
- MMO) {
- assert(getMask().getValueType().getVectorNumElements() ==
- getValue().getValueType().getVectorNumElements() &&
- "Vector width mismatch between mask and data");
- assert(getIndex().getValueType().getVectorNumElements() ==
- getValue().getValueType().getVectorNumElements() &&
- "Vector width mismatch between index and data");
- }
+ MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ EVT MemVT, MachineMemOperand *MMO)
+ : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO) {}
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MSCATTER;
@@ -2183,12 +1989,8 @@ public:
private:
friend class SelectionDAG;
- MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs)
- : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
-
- /// Operands for this instruction, if they fit here. If
- /// they don't, this field is unused.
- SDUse LocalOperands[4];
+ MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs)
+ : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
/// Memory reference descriptions for this instruction.
mmo_iterator MemRefs;
@@ -2264,8 +2066,13 @@ template <> struct GraphTraits<SDNode*> {
}
};
-/// The largest SDNode class.
-typedef MaskedGatherScatterSDNode LargestSDNode;
+/// A representation of the largest SDNode, for use in sizeof().
+///
+/// This needs to be a union because the largest node differs on 32 bit systems
+/// with 4 and 8 byte pointer alignment, respectively.
+typedef AlignedCharArrayUnion<AtomicSDNode, TargetIndexSDNode,
+ BlockAddressSDNode, GlobalAddressSDNode>
+ LargestSDNode;
/// The SDNode class with the greatest alignment requirement.
typedef GlobalAddressSDNode MostAlignedSDNode;
diff --git a/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/include/llvm/CodeGen/SelectionDAGTargetInfo.h
new file mode 100644
index 0000000000000..ac5092af8def3
--- /dev/null
+++ b/include/llvm/CodeGen/SelectionDAGTargetInfo.h
@@ -0,0 +1,156 @@
+//==-- llvm/CodeGen/SelectionDAGTargetInfo.h - SelectionDAG Info -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SelectionDAGTargetInfo class, which targets can
+// subclass to parameterize the SelectionDAG lowering and instruction
+// selection process.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H
+#define LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H
+
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/CodeGen.h"
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+/// Targets can subclass this to parameterize the
+/// SelectionDAG lowering and instruction selection process.
+///
+class SelectionDAGTargetInfo {
+ SelectionDAGTargetInfo(const SelectionDAGTargetInfo &) = delete;
+ void operator=(const SelectionDAGTargetInfo &) = delete;
+
+public:
+ explicit SelectionDAGTargetInfo() = default;
+ virtual ~SelectionDAGTargetInfo();
+
+ /// Emit target-specific code that performs a memcpy.
+ /// This can be used by targets to provide code sequences for cases
+ /// that don't fit the target's parameters for simple loads/stores and can be
+ /// more efficient than using a library call. This function can return a null
+ /// SDValue if the target declines to use custom code and a different
+ /// lowering strategy should be used.
+ ///
+ /// If AlwaysInline is true, the size is constant and the target should not
+ /// emit any calls and is strongly encouraged to attempt to emit inline code
+ /// even if it is beyond the usual threshold because this intrinsic is being
+ /// expanded in a place where calls are not feasible (e.g. within the prologue
+ /// for another call). If the target chooses to decline an AlwaysInline
+ /// request here, legalize will resort to using simple loads and stores.
+ virtual SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl,
+ SDValue Chain, SDValue Op1,
+ SDValue Op2, SDValue Op3,
+ unsigned Align, bool isVolatile,
+ bool AlwaysInline,
+ MachinePointerInfo DstPtrInfo,
+ MachinePointerInfo SrcPtrInfo) const {
+ return SDValue();
+ }
+
+ /// Emit target-specific code that performs a memmove.
+ /// This can be used by targets to provide code sequences for cases
+ /// that don't fit the target's parameters for simple loads/stores and can be
+ /// more efficient than using a library call. This function can return a null
+ /// SDValue if the target declines to use custom code and a different
+ /// lowering strategy should be used.
+ virtual SDValue EmitTargetCodeForMemmove(
+ SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Op1,
+ SDValue Op2, SDValue Op3, unsigned Align, bool isVolatile,
+ MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
+ return SDValue();
+ }
+
+ /// Emit target-specific code that performs a memset.
+ /// This can be used by targets to provide code sequences for cases
+ /// that don't fit the target's parameters for simple stores and can be more
+ /// efficient than using a library call. This function can return a null
+ /// SDValue if the target declines to use custom code and a different
+ /// lowering strategy should be used.
+ virtual SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl,
+ SDValue Chain, SDValue Op1,
+ SDValue Op2, SDValue Op3,
+ unsigned Align, bool isVolatile,
+ MachinePointerInfo DstPtrInfo) const {
+ return SDValue();
+ }
+
+ /// Emit target-specific code that performs a memcmp, in cases where that is
+ /// faster than a libcall. The first returned SDValue is the result of the
+ /// memcmp and the second is the chain. Both SDValues can be null if a normal
+ /// libcall should be used.
+ virtual std::pair<SDValue, SDValue>
+ EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
+ SDValue Op1, SDValue Op2, SDValue Op3,
+ MachinePointerInfo Op1PtrInfo,
+ MachinePointerInfo Op2PtrInfo) const {
+ return std::make_pair(SDValue(), SDValue());
+ }
+
+ /// Emit target-specific code that performs a memchr, in cases where that is
+ /// faster than a libcall. The first returned SDValue is the result of the
+ /// memchr and the second is the chain. Both SDValues can be null if a normal
+ /// libcall should be used.
+ virtual std::pair<SDValue, SDValue>
+ EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
+ SDValue Src, SDValue Char, SDValue Length,
+ MachinePointerInfo SrcPtrInfo) const {
+ return std::make_pair(SDValue(), SDValue());
+ }
+
+ /// Emit target-specific code that performs a strcpy or stpcpy, in cases
+ /// where that is faster than a libcall.
+ /// The first returned SDValue is the result of the copy (the start
+ /// of the destination string for strcpy, a pointer to the null terminator
+ /// for stpcpy) and the second is the chain. Both SDValues can be null
+ /// if a normal libcall should be used.
+ virtual std::pair<SDValue, SDValue>
+ EmitTargetCodeForStrcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
+ SDValue Dest, SDValue Src,
+ MachinePointerInfo DestPtrInfo,
+ MachinePointerInfo SrcPtrInfo, bool isStpcpy) const {
+ return std::make_pair(SDValue(), SDValue());
+ }
+
+ /// Emit target-specific code that performs a strcmp, in cases where that is
+ /// faster than a libcall.
+ /// The first returned SDValue is the result of the strcmp and the second is
+ /// the chain. Both SDValues can be null if a normal libcall should be used.
+ virtual std::pair<SDValue, SDValue>
+ EmitTargetCodeForStrcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
+ SDValue Op1, SDValue Op2,
+ MachinePointerInfo Op1PtrInfo,
+ MachinePointerInfo Op2PtrInfo) const {
+ return std::make_pair(SDValue(), SDValue());
+ }
+
+ virtual std::pair<SDValue, SDValue>
+ EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
+ SDValue Src, MachinePointerInfo SrcPtrInfo) const {
+ return std::make_pair(SDValue(), SDValue());
+ }
+
+ virtual std::pair<SDValue, SDValue>
+ EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
+ SDValue Src, SDValue MaxLength,
+ MachinePointerInfo SrcPtrInfo) const {
+ return std::make_pair(SDValue(), SDValue());
+ }
+ // Return true when the decision to generate FMA's (or FMS, FMLA etc) rather
+ // than FMUL and ADD is delegated to the machine combiner.
+ virtual bool generateFMAsInMachineCombiner(CodeGenOpt::Level OptLevel) const {
+ return false;
+ }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 7b621bee259ff..afb0288b024fb 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/include/llvm/CodeGen/SlotIndexes.h
@@ -66,7 +66,6 @@ namespace llvm {
bool isPoisoned() const { return (reinterpret_cast<intptr_t>(mi) & 0x1) == 0x1; }
#endif // EXPENSIVE_CHECKS
-
};
template <>
@@ -99,7 +98,7 @@ namespace llvm {
Slot_Block,
/// Early-clobber register use/def slot. A live range defined at
- /// Slot_EarlyCLobber interferes with normal live ranges killed at
+ /// Slot_EarlyClobber interferes with normal live ranges killed at
/// Slot_Register. Also used as the kill slot for live ranges tied to an
/// early-clobber def.
Slot_EarlyClobber,
@@ -213,6 +212,12 @@ namespace llvm {
return A.listEntry()->getIndex() < B.listEntry()->getIndex();
}
+ /// Return true if A refers to the same instruction as B or an earlier one.
+ /// This is equivalent to !isEarlierInstr(B, A).
+ static bool isEarlierEqualInstr(SlotIndex A, SlotIndex B) {
+ return !isEarlierInstr(B, A);
+ }
+
/// Return the distance from this index to the given one.
int distance(SlotIndex other) const {
return other.getIndex() - getIndex();
@@ -302,7 +307,6 @@ namespace llvm {
SlotIndex getPrevIndex() const {
return SlotIndex(&*--listEntry()->getIterator(), getSlot());
}
-
};
template <> struct isPodLike<SlotIndex> { static const bool value = true; };
@@ -376,7 +380,7 @@ namespace llvm {
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
}
- ~SlotIndexes() {
+ ~SlotIndexes() override {
// The indexList's nodes are all allocated in the BumpPtrAllocator.
indexList.clearAndLeakNodesUnsafely();
}
@@ -410,14 +414,14 @@ namespace llvm {
/// Returns true if the given machine instr is mapped to an index,
/// otherwise returns false.
- bool hasIndex(const MachineInstr *instr) const {
- return mi2iMap.count(instr);
+ bool hasIndex(const MachineInstr &instr) const {
+ return mi2iMap.count(&instr);
}
/// Returns the base index for the given instruction.
- SlotIndex getInstructionIndex(const MachineInstr *MI) const {
+ SlotIndex getInstructionIndex(const MachineInstr &MI) const {
// Instructions inside a bundle have the same number as the bundle itself.
- Mi2IndexMap::const_iterator itr = mi2iMap.find(getBundleStart(MI));
+ Mi2IndexMap::const_iterator itr = mi2iMap.find(&getBundleStart(MI));
assert(itr != mi2iMap.end() && "Instruction not found in maps.");
return itr->second;
}
@@ -443,15 +447,15 @@ namespace llvm {
/// getIndexBefore - Returns the index of the last indexed instruction
/// before MI, or the start index of its basic block.
/// MI is not required to have an index.
- SlotIndex getIndexBefore(const MachineInstr *MI) const {
- const MachineBasicBlock *MBB = MI->getParent();
+ SlotIndex getIndexBefore(const MachineInstr &MI) const {
+ const MachineBasicBlock *MBB = MI.getParent();
assert(MBB && "MI must be inserted inna basic block");
MachineBasicBlock::const_iterator I = MI, B = MBB->begin();
for (;;) {
if (I == B)
return getMBBStartIdx(MBB);
--I;
- Mi2IndexMap::const_iterator MapItr = mi2iMap.find(I);
+ Mi2IndexMap::const_iterator MapItr = mi2iMap.find(&*I);
if (MapItr != mi2iMap.end())
return MapItr->second;
}
@@ -460,15 +464,15 @@ namespace llvm {
/// getIndexAfter - Returns the index of the first indexed instruction
/// after MI, or the end index of its basic block.
/// MI is not required to have an index.
- SlotIndex getIndexAfter(const MachineInstr *MI) const {
- const MachineBasicBlock *MBB = MI->getParent();
+ SlotIndex getIndexAfter(const MachineInstr &MI) const {
+ const MachineBasicBlock *MBB = MI.getParent();
assert(MBB && "MI must be inserted inna basic block");
MachineBasicBlock::const_iterator I = MI, E = MBB->end();
for (;;) {
++I;
if (I == E)
return getMBBEndIdx(MBB);
- Mi2IndexMap::const_iterator MapItr = mi2iMap.find(I);
+ Mi2IndexMap::const_iterator MapItr = mi2iMap.find(&*I);
if (MapItr != mi2iMap.end())
return MapItr->second;
}
@@ -573,25 +577,25 @@ namespace llvm {
/// If Late is set and there are null indexes between mi's neighboring
/// instructions, create the new index after the null indexes instead of
/// before them.
- SlotIndex insertMachineInstrInMaps(MachineInstr *mi, bool Late = false) {
- assert(!mi->isInsideBundle() &&
+ SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late = false) {
+ assert(!MI.isInsideBundle() &&
"Instructions inside bundles should use bundle start's slot.");
- assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed.");
+ assert(mi2iMap.find(&MI) == mi2iMap.end() && "Instr already indexed.");
// Numbering DBG_VALUE instructions could cause code generation to be
// affected by debug information.
- assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions.");
+ assert(!MI.isDebugValue() && "Cannot number DBG_VALUE instructions.");
- assert(mi->getParent() != nullptr && "Instr must be added to function.");
+ assert(MI.getParent() != nullptr && "Instr must be added to function.");
- // Get the entries where mi should be inserted.
+ // Get the entries where MI should be inserted.
IndexList::iterator prevItr, nextItr;
if (Late) {
- // Insert mi's index immediately before the following instruction.
- nextItr = getIndexAfter(mi).listEntry()->getIterator();
+ // Insert MI's index immediately before the following instruction.
+ nextItr = getIndexAfter(MI).listEntry()->getIterator();
prevItr = std::prev(nextItr);
} else {
- // Insert mi's index immediately after the preceding instruction.
- prevItr = getIndexBefore(mi).listEntry()->getIterator();
+ // Insert MI's index immediately after the preceding instruction.
+ prevItr = getIndexBefore(MI).listEntry()->getIterator();
nextItr = std::next(prevItr);
}
@@ -600,27 +604,27 @@ namespace llvm {
unsigned dist = ((nextItr->getIndex() - prevItr->getIndex())/2) & ~3u;
unsigned newNumber = prevItr->getIndex() + dist;
- // Insert a new list entry for mi.
+ // Insert a new list entry for MI.
IndexList::iterator newItr =
- indexList.insert(nextItr, createEntry(mi, newNumber));
+ indexList.insert(nextItr, createEntry(&MI, newNumber));
// Renumber locally if we need to.
if (dist == 0)
renumberIndexes(newItr);
SlotIndex newIndex(&*newItr, SlotIndex::Slot_Block);
- mi2iMap.insert(std::make_pair(mi, newIndex));
+ mi2iMap.insert(std::make_pair(&MI, newIndex));
return newIndex;
}
/// Remove the given machine instruction from the mapping.
- void removeMachineInstrFromMaps(MachineInstr *mi) {
+ void removeMachineInstrFromMaps(MachineInstr &MI) {
// remove index -> MachineInstr and
// MachineInstr -> index mappings
- Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi);
+ Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI);
if (mi2iItr != mi2iMap.end()) {
IndexListEntry *miEntry(mi2iItr->second.listEntry());
- assert(miEntry->getInstr() == mi && "Instruction indexes broken.");
+ assert(miEntry->getInstr() == &MI && "Instruction indexes broken.");
// FIXME: Eventually we want to actually delete these indexes.
miEntry->setInstr(nullptr);
mi2iMap.erase(mi2iItr);
@@ -629,17 +633,17 @@ namespace llvm {
/// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in
/// maps used by register allocator.
- void replaceMachineInstrInMaps(MachineInstr *mi, MachineInstr *newMI) {
- Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi);
+ void replaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI) {
+ Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI);
if (mi2iItr == mi2iMap.end())
return;
SlotIndex replaceBaseIndex = mi2iItr->second;
IndexListEntry *miEntry(replaceBaseIndex.listEntry());
- assert(miEntry->getInstr() == mi &&
+ assert(miEntry->getInstr() == &MI &&
"Mismatched instruction in index tables.");
- miEntry->setInstr(newMI);
+ miEntry->setInstr(&NewMI);
mi2iMap.erase(mi2iItr);
- mi2iMap.insert(std::make_pair(newMI, replaceBaseIndex));
+ mi2iMap.insert(std::make_pair(&NewMI, replaceBaseIndex));
}
/// Add the given MachineBasicBlock into the maps.
@@ -703,15 +707,13 @@ namespace llvm {
indexList.erase(entry);
#endif
}
-
};
-
// Specialize IntervalMapInfo for half-open slot index intervals.
template <>
struct IntervalMapInfo<SlotIndex> : IntervalMapHalfOpenInfo<SlotIndex> {
};
-}
+} // end namespace llvm
#endif // LLVM_CODEGEN_SLOTINDEXES_H
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 972a616ad779a..918848f6b2a13 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -14,8 +14,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Debug.h"
-#include <map>
#include <vector>
namespace llvm {
diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h
index 8cef85cb44852..1b3c0eb4a4d0a 100644
--- a/include/llvm/CodeGen/StackProtector.h
+++ b/include/llvm/CodeGen/StackProtector.h
@@ -75,6 +75,12 @@ private:
/// times.
SmallPtrSet<const PHINode *, 16> VisitedPHIs;
+ // A prologue is generated.
+ bool HasPrologue = false;
+
+ // IR checking code is generated.
+ bool HasIRCheck = false;
+
/// InsertStackProtectors - Insert code into the prologue and epilogue of
/// the function.
///
@@ -120,6 +126,10 @@ public:
}
SSPLayoutKind getSSPLayout(const AllocaInst *AI) const;
+
+ // Return true if StackProtector is supposed to be handled by SelectionDAG.
+ bool shouldEmitSDCheck(const BasicBlock &BB) const;
+
void adjustForColoring(const AllocaInst *From, const AllocaInst *To);
bool runOnFunction(Function &Fn) override;
diff --git a/include/llvm/CodeGen/TailDuplicator.h b/include/llvm/CodeGen/TailDuplicator.h
new file mode 100644
index 0000000000000..8e65199418a6b
--- /dev/null
+++ b/include/llvm/CodeGen/TailDuplicator.h
@@ -0,0 +1,92 @@
+//===-- llvm/CodeGen/TailDuplicator.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TailDuplicator class. Used by the
+// TailDuplication pass, and MachineBlockPlacement.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_TAILDUPLICATOR_H
+#define LLVM_CODEGEN_TAILDUPLICATOR_H
+
+#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineSSAUpdater.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+namespace llvm {
+
+/// Utility class to perform tail duplication.
+class TailDuplicator {
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ const MachineBranchProbabilityInfo *MBPI;
+ const MachineModuleInfo *MMI;
+ MachineRegisterInfo *MRI;
+ bool PreRegAlloc;
+
+ // A list of virtual registers for which to update SSA form.
+ SmallVector<unsigned, 16> SSAUpdateVRs;
+
+ // For each virtual register in SSAUpdateVals keep a list of source virtual
+ // registers.
+ typedef std::vector<std::pair<MachineBasicBlock *, unsigned>> AvailableValsTy;
+
+ DenseMap<unsigned, AvailableValsTy> SSAUpdateVals;
+
+public:
+ void initMF(MachineFunction &MF, const MachineModuleInfo *MMI,
+ const MachineBranchProbabilityInfo *MBPI);
+ bool tailDuplicateBlocks(MachineFunction &MF);
+ static bool isSimpleBB(MachineBasicBlock *TailBB);
+ bool shouldTailDuplicate(const MachineFunction &MF, bool IsSimple,
+ MachineBasicBlock &TailBB);
+ bool tailDuplicateAndUpdate(MachineFunction &MF, bool IsSimple,
+ MachineBasicBlock *MBB);
+
+private:
+ typedef TargetInstrInfo::RegSubRegPair RegSubRegPair;
+
+ void addSSAUpdateEntry(unsigned OrigReg, unsigned NewReg,
+ MachineBasicBlock *BB);
+ void processPHI(MachineInstr *MI, MachineBasicBlock *TailBB,
+ MachineBasicBlock *PredBB,
+ DenseMap<unsigned, RegSubRegPair> &LocalVRMap,
+ SmallVectorImpl<std::pair<unsigned, RegSubRegPair>> &Copies,
+ const DenseSet<unsigned> &UsedByPhi, bool Remove);
+ void duplicateInstruction(MachineInstr *MI, MachineBasicBlock *TailBB,
+ MachineBasicBlock *PredBB, MachineFunction &MF,
+ DenseMap<unsigned, RegSubRegPair> &LocalVRMap,
+ const DenseSet<unsigned> &UsedByPhi);
+ void updateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead,
+ SmallVectorImpl<MachineBasicBlock *> &TDBBs,
+ SmallSetVector<MachineBasicBlock *, 8> &Succs);
+ bool canCompletelyDuplicateBB(MachineBasicBlock &BB);
+ bool duplicateSimpleBB(MachineBasicBlock *TailBB,
+ SmallVectorImpl<MachineBasicBlock *> &TDBBs,
+ const DenseSet<unsigned> &RegsUsedByPhi,
+ SmallVectorImpl<MachineInstr *> &Copies);
+ bool tailDuplicate(MachineFunction &MF, bool IsSimple,
+ MachineBasicBlock *TailBB,
+ SmallVectorImpl<MachineBasicBlock *> &TDBBs,
+ SmallVectorImpl<MachineInstr *> &Copies);
+ void appendCopies(MachineBasicBlock *MBB,
+ SmallVectorImpl<std::pair<unsigned,RegSubRegPair>> &CopyInfos,
+ SmallVectorImpl<MachineInstr *> &Copies);
+
+ void removeDeadBlock(MachineBasicBlock *MBB);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 2f1379131cbdc..c856435f5ddca 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -15,7 +15,7 @@
#ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
#define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
@@ -23,7 +23,6 @@ namespace llvm {
class MachineModuleInfo;
class Mangler;
class MCAsmInfo;
- class MCExpr;
class MCSection;
class MCSectionMachO;
class MCSymbol;
@@ -36,6 +35,10 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
bool UseInitArray;
mutable unsigned NextUniqueID = 0;
+protected:
+ MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =
+ MCSymbolRefExpr::VK_None;
+
public:
TargetLoweringObjectFileELF() : UseInitArray(false) {}
@@ -47,7 +50,8 @@ public:
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
- const Constant *C) const override;
+ const Constant *C,
+ unsigned &Align) const override;
MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler &Mang,
@@ -81,6 +85,10 @@ public:
const MCSymbol *KeySym) const override;
MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;
+
+ const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
+ const GlobalValue *RHS, Mangler &Mang,
+ const TargetMachine &TM) const override;
};
@@ -104,7 +112,8 @@ public:
const TargetMachine &TM) const override;
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
- const Constant *C) const override;
+ const Constant *C,
+ unsigned &Align) const override;
/// The mach-o version of this method defaults to returning a stub reference.
const MCExpr *
@@ -131,6 +140,8 @@ public:
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
+ mutable unsigned NextUniqueID = 0;
+
public:
~TargetLoweringObjectFileCOFF() override {}
diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h
new file mode 100644
index 0000000000000..9309655a972ed
--- /dev/null
+++ b/include/llvm/CodeGen/TargetPassConfig.h
@@ -0,0 +1,376 @@
+//===-- TargetPassConfig.h - Code Generation pass options -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// Target-Independent Code Generator Pass Configuration Options pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_TARGETPASSCONFIG_H
+#define LLVM_CODEGEN_TARGETPASSCONFIG_H
+
+#include "llvm/Pass.h"
+#include "llvm/Support/CodeGen.h"
+#include <string>
+
+namespace llvm {
+
+class PassConfigImpl;
+class ScheduleDAGInstrs;
+class TargetMachine;
+struct MachineSchedContext;
+
+// The old pass manager infrastructure is hidden in a legacy namespace now.
+namespace legacy {
+class PassManagerBase;
+}
+using legacy::PassManagerBase;
+
+/// Discriminated union of Pass ID types.
+///
+/// The PassConfig API prefers dealing with IDs because they are safer and more
+/// efficient. IDs decouple configuration from instantiation. This way, when a
+/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to
+/// refer to a Pass pointer after adding it to a pass manager, which deletes
+/// redundant pass instances.
+///
+/// However, it is convient to directly instantiate target passes with
+/// non-default ctors. These often don't have a registered PassInfo. Rather than
+/// force all target passes to implement the pass registry boilerplate, allow
+/// the PassConfig API to handle either type.
+///
+/// AnalysisID is sadly char*, so PointerIntPair won't work.
+class IdentifyingPassPtr {
+ union {
+ AnalysisID ID;
+ Pass *P;
+ };
+ bool IsInstance;
+public:
+ IdentifyingPassPtr() : P(nullptr), IsInstance(false) {}
+ IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {}
+ IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {}
+
+ bool isValid() const { return P; }
+ bool isInstance() const { return IsInstance; }
+
+ AnalysisID getID() const {
+ assert(!IsInstance && "Not a Pass ID");
+ return ID;
+ }
+ Pass *getInstance() const {
+ assert(IsInstance && "Not a Pass Instance");
+ return P;
+ }
+};
+
+template <> struct isPodLike<IdentifyingPassPtr> {
+ static const bool value = true;
+};
+
+/// Target-Independent Code Generator Pass Configuration Options.
+///
+/// This is an ImmutablePass solely for the purpose of exposing CodeGen options
+/// to the internals of other CodeGen passes.
+class TargetPassConfig : public ImmutablePass {
+public:
+ /// Pseudo Pass IDs. These are defined within TargetPassConfig because they
+ /// are unregistered pass IDs. They are only useful for use with
+ /// TargetPassConfig APIs to identify multiple occurrences of the same pass.
+ ///
+
+ /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early
+ /// during codegen, on SSA form.
+ static char EarlyTailDuplicateID;
+
+ /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine
+ /// optimization after regalloc.
+ static char PostRAMachineLICMID;
+
+private:
+ PassManagerBase *PM;
+ AnalysisID StartBefore, StartAfter;
+ AnalysisID StopAfter;
+ bool Started;
+ bool Stopped;
+ bool AddingMachinePasses;
+
+protected:
+ TargetMachine *TM;
+ PassConfigImpl *Impl; // Internal data structures
+ bool Initialized; // Flagged after all passes are configured.
+
+ // Target Pass Options
+ // Targets provide a default setting, user flags override.
+ //
+ bool DisableVerify;
+
+ /// Default setting for -enable-tail-merge on this target.
+ bool EnableTailMerge;
+
+public:
+ TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
+ // Dummy constructor.
+ TargetPassConfig();
+
+ ~TargetPassConfig() override;
+
+ static char ID;
+
+ /// Get the right type of TargetMachine for this target.
+ template<typename TMC> TMC &getTM() const {
+ return *static_cast<TMC*>(TM);
+ }
+
+ //
+ void setInitialized() { Initialized = true; }
+
+ CodeGenOpt::Level getOptLevel() const;
+
+ /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
+ /// a portion of the normal code-gen pass sequence.
+ ///
+ /// If the StartAfter and StartBefore pass ID is zero, then compilation will
+ /// begin at the normal point; otherwise, clear the Started flag to indicate
+ /// that passes should not be added until the starting pass is seen. If the
+ /// Stop pass ID is zero, then compilation will continue to the end.
+ ///
+ /// This function expects that at least one of the StartAfter or the
+ /// StartBefore pass IDs is null.
+ void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter,
+ AnalysisID StopAfter) {
+ if (StartAfter)
+ assert(!StartBefore && "Start after and start before passes are given");
+ this->StartBefore = StartBefore;
+ this->StartAfter = StartAfter;
+ this->StopAfter = StopAfter;
+ Started = (StartAfter == nullptr) && (StartBefore == nullptr);
+ }
+
+ void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
+
+ bool getEnableTailMerge() const { return EnableTailMerge; }
+ void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, 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.
+ void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID);
+
+ /// Insert InsertedPassID pass after TargetPassID pass.
+ void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID,
+ bool VerifyAfter = true, bool PrintAfter = true);
+
+ /// Allow the target to enable a specific standard pass by default.
+ void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); }
+
+ /// Allow the target to disable a specific standard pass by default.
+ void disablePass(AnalysisID PassID) {
+ substitutePass(PassID, IdentifyingPassPtr());
+ }
+
+ /// Return the pass substituted for StandardID by the target.
+ /// If no substitution exists, return StandardID.
+ IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const;
+
+ /// Return true if the pass has been substituted by the target or
+ /// overridden on the command line.
+ bool isPassSubstitutedOrOverridden(AnalysisID ID) const;
+
+ /// Return true if the optimized regalloc pipeline is enabled.
+ bool getOptimizeRegAlloc() const;
+
+ /// Return true if shrink wrapping is enabled.
+ bool getEnableShrinkWrap() const;
+
+ /// Return true if the default global register allocator is in use and
+ /// has not be overriden on the command line with '-regalloc=...'
+ bool usingDefaultRegAlloc() const;
+
+ /// Add common target configurable passes that perform LLVM IR to IR
+ /// transforms following machine independent optimization.
+ virtual void addIRPasses();
+
+ /// Add passes to lower exception handling for the code generator.
+ void addPassesToHandleExceptions();
+
+ /// Add pass to prepare the LLVM IR for code generation. This should be done
+ /// before exception handling preparation passes.
+ virtual void addCodeGenPrepare();
+
+ /// Add common passes that perform LLVM IR to IR transforms in preparation for
+ /// instruction selection.
+ virtual void addISelPrepare();
+
+ /// addInstSelector - This method should install an instruction selector pass,
+ /// which converts from LLVM code to machine instructions.
+ virtual bool addInstSelector() {
+ return true;
+ }
+
+ /// This method should install an IR translator pass, which converts from
+ /// LLVM code to machine instructions with possibly generic opcodes.
+ virtual bool addIRTranslator() { return true; }
+
+ /// This method may be implemented by targets that want to run passes
+ /// immediately before the register bank selection.
+ virtual void addPreRegBankSelect() {}
+
+ /// This method should install a register bank selector pass, which
+ /// assigns register banks to virtual registers without a register
+ /// class or register banks.
+ virtual bool addRegBankSelect() { return true; }
+
+ /// Add the complete, standard set of LLVM CodeGen passes.
+ /// Fully developed targets will not generally override this.
+ virtual void addMachinePasses();
+
+ /// Create an instance of ScheduleDAGInstrs to be run within the standard
+ /// MachineScheduler pass for this function and target at the current
+ /// optimization level.
+ ///
+ /// This can also be used to plug a new MachineSchedStrategy into an instance
+ /// of the standard ScheduleDAGMI:
+ /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /*RemoveKillFlags=*/false)
+ ///
+ /// Return NULL to select the default (generic) machine scheduler.
+ virtual ScheduleDAGInstrs *
+ createMachineScheduler(MachineSchedContext *C) const {
+ return nullptr;
+ }
+
+ /// Similar to createMachineScheduler but used when postRA machine scheduling
+ /// is enabled.
+ virtual ScheduleDAGInstrs *
+ createPostMachineScheduler(MachineSchedContext *C) const {
+ return nullptr;
+ }
+
+ /// printAndVerify - Add a pass to dump then verify the machine function, if
+ /// those steps are enabled.
+ ///
+ void printAndVerify(const std::string &Banner);
+
+ /// Add a pass to print the machine function if printing is enabled.
+ void addPrintPass(const std::string &Banner);
+
+ /// Add a pass to perform basic verification of the machine function if
+ /// verification is enabled.
+ void addVerifyPass(const std::string &Banner);
+
+protected:
+ // Helper to verify the analysis is really immutable.
+ void setOpt(bool &Opt, bool Val);
+
+ /// Methods with trivial inline returns are convenient points in the common
+ /// codegen pass pipeline where targets may insert passes. Methods with
+ /// out-of-line standard implementations are major CodeGen stages called by
+ /// addMachinePasses. Some targets may override major stages when inserting
+ /// passes is insufficient, but maintaining overriden stages is more work.
+ ///
+
+ /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM
+ /// passes (which are run just before instruction selector).
+ virtual bool addPreISel() {
+ return true;
+ }
+
+ /// addMachineSSAOptimization - Add standard passes that optimize machine
+ /// instructions in SSA form.
+ virtual void addMachineSSAOptimization();
+
+ /// Add passes that optimize instruction level parallelism for out-of-order
+ /// targets. These passes are run while the machine code is still in SSA
+ /// form, so they can use MachineTraceMetrics to control their heuristics.
+ ///
+ /// All passes added here should preserve the MachineDominatorTree,
+ /// MachineLoopInfo, and MachineTraceMetrics analyses.
+ virtual bool addILPOpts() {
+ return false;
+ }
+
+ /// This method may be implemented by targets that want to run passes
+ /// immediately before register allocation.
+ virtual void addPreRegAlloc() { }
+
+ /// createTargetRegisterAllocator - Create the register allocator pass for
+ /// this target at the current optimization level.
+ virtual FunctionPass *createTargetRegisterAllocator(bool Optimized);
+
+ /// addFastRegAlloc - Add the minimum set of target-independent passes that
+ /// are required for fast register allocation.
+ virtual void addFastRegAlloc(FunctionPass *RegAllocPass);
+
+ /// addOptimizedRegAlloc - Add passes related to register allocation.
+ /// LLVMTargetMachine provides standard regalloc passes for most targets.
+ virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass);
+
+ /// addPreRewrite - Add passes to the optimized register allocation pipeline
+ /// after register allocation is complete, but before virtual registers are
+ /// rewritten to physical registers.
+ ///
+ /// These passes must preserve VirtRegMap and LiveIntervals, and when running
+ /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix.
+ /// When these passes run, VirtRegMap contains legal physreg assignments for
+ /// all virtual registers.
+ virtual bool addPreRewrite() {
+ return false;
+ }
+
+ /// This method may be implemented by targets that want to run passes after
+ /// register allocation pass pipeline but before prolog-epilog insertion.
+ virtual void addPostRegAlloc() { }
+
+ /// Add passes that optimize machine instructions after register allocation.
+ virtual void addMachineLateOptimization();
+
+ /// This method may be implemented by targets that want to run passes after
+ /// prolog-epilog insertion and before the second instruction scheduling pass.
+ virtual void addPreSched2() { }
+
+ /// addGCPasses - Add late codegen passes that analyze code for garbage
+ /// collection. This should return true if GC info should be printed after
+ /// these passes.
+ virtual bool addGCPasses();
+
+ /// Add standard basic block placement passes.
+ virtual void addBlockPlacement();
+
+ /// This pass may be implemented by targets that want to run passes
+ /// immediately before machine code is emitted.
+ virtual void addPreEmitPass() { }
+
+ /// Utilities for targets to add passes to the pass manager.
+ ///
+
+ /// Add a CodeGen pass at this point in the pipeline after checking overrides.
+ /// Return the pass that was added, or zero if no pass was added.
+ /// @p printAfter if true and adding a machine function pass add an extra
+ /// machine printer pass afterwards
+ /// @p verifyAfter if true and adding a machine function pass add an extra
+ /// machine verification pass afterwards.
+ AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true,
+ bool printAfter = true);
+
+ /// Add a pass to the PassManager if that pass is supposed to be run, as
+ /// determined by the StartAfter and StopAfter options. Takes ownership of the
+ /// pass.
+ /// @p printAfter if true and adding a machine function pass add an extra
+ /// machine printer pass afterwards
+ /// @p verifyAfter if true and adding a machine function pass add an extra
+ /// machine verification pass afterwards.
+ void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true);
+
+ /// addMachinePasses helper to create the target-selected or overriden
+ /// regalloc pass.
+ FunctionPass *createRegAllocPass(bool Optimized);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/UnreachableBlockElim.h b/include/llvm/CodeGen/UnreachableBlockElim.h
new file mode 100644
index 0000000000000..3e7afd4cd4337
--- /dev/null
+++ b/include/llvm/CodeGen/UnreachableBlockElim.h
@@ -0,0 +1,37 @@
+//===-- UnreachableBlockElim.h - Remove unreachable blocks for codegen --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass is an extremely simple version of the SimplifyCFG pass. Its sole
+// job is to delete LLVM basic blocks that are not reachable from the entry
+// node. To do this, it performs a simple depth first traversal of the CFG,
+// then deletes any unvisited nodes.
+//
+// Note that this pass is really a hack. In particular, the instruction
+// selectors for various targets should just not generate code for unreachable
+// blocks. Until LLVM has a more systematic way of defining instruction
+// selectors, however, we cannot really expect them to handle additional
+// complexity.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_UNREACHABLEBLOCKELIM_H
+#define LLVM_LIB_CODEGEN_UNREACHABLEBLOCKELIM_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class UnreachableBlockElimPass
+ : public PassInfoMixin<UnreachableBlockElimPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_LIB_CODEGEN_UNREACHABLEBLOCKELIM_H
diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h
index 929eb88a0393d..524a90803df89 100644
--- a/include/llvm/CodeGen/ValueTypes.h
+++ b/include/llvm/CodeGen/ValueTypes.h
@@ -124,6 +124,11 @@ namespace llvm {
return isSimple() ? V.isInteger() : isExtendedInteger();
}
+ /// isScalarInteger - 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.
bool isVector() const {
return isSimple() ? V.isVector() : isExtendedVector();
@@ -367,6 +372,7 @@ namespace llvm {
unsigned NumElements);
bool isExtendedFloatingPoint() const LLVM_READONLY;
bool isExtendedInteger() const LLVM_READONLY;
+ bool isExtendedScalarInteger() const LLVM_READONLY;
bool isExtendedVector() const LLVM_READONLY;
bool isExtended16BitVector() const LLVM_READONLY;
bool isExtended32BitVector() const LLVM_READONLY;
@@ -378,7 +384,7 @@ namespace llvm {
bool isExtended2048BitVector() const LLVM_READONLY;
EVT getExtendedVectorElementType() const;
unsigned getExtendedVectorNumElements() const LLVM_READONLY;
- unsigned getExtendedSizeInBits() const;
+ unsigned getExtendedSizeInBits() const LLVM_READONLY;
};
} // End llvm namespace
diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td
index f29ec42714e8d..f7b1661d7451b 100644
--- a/include/llvm/CodeGen/ValueTypes.td
+++ b/include/llvm/CodeGen/ValueTypes.td
@@ -39,8 +39,8 @@ def v8i1 : ValueType<8 , 15>; // 8 x i1 vector value
def v16i1 : ValueType<16, 16>; // 16 x i1 vector value
def v32i1 : ValueType<32 , 17>; // 32 x i1 vector value
def v64i1 : ValueType<64 , 18>; // 64 x i1 vector value
-def v512i1 : ValueType<512, 19>; // 512 x i8 vector value
-def v1024i1: ValueType<1024,20>; //1024 x i8 vector value
+def v512i1 : ValueType<512, 19>; // 512 x i1 vector value
+def v1024i1: ValueType<1024,20>; //1024 x i1 vector value
def v1i8 : ValueType<16, 21>; // 1 x i8 vector value
def v2i8 : ValueType<16 , 22>; // 2 x i8 vector value
@@ -96,24 +96,24 @@ def x86mmx : ValueType<64 , 64>; // X86 MMX value
def FlagVT : ValueType<0 , 65>; // Pre-RA sched glue
def isVoid : ValueType<0 , 66>; // Produces no value
def untyped: ValueType<8 , 67>; // Produces an untyped value
-def token : ValueType<0 , 249>; // TokenTy
-def MetadataVT: ValueType<0, 250>; // Metadata
+def token : ValueType<0 , 120>; // TokenTy
+def MetadataVT: ValueType<0, 121>; // Metadata
// Pseudo valuetype mapped to the current pointer size to any address space.
// Should only be used in TableGen.
-def iPTRAny : ValueType<0, 251>;
+def iPTRAny : ValueType<0, 122>;
// Pseudo valuetype to represent "vector of any size"
-def vAny : ValueType<0 , 252>;
+def vAny : ValueType<0 , 123>;
// Pseudo valuetype to represent "float of any format"
-def fAny : ValueType<0 , 253>;
+def fAny : ValueType<0 , 124>;
// Pseudo valuetype to represent "integer of any bit width"
-def iAny : ValueType<0 , 254>;
+def iAny : ValueType<0 , 125>;
// Pseudo valuetype mapped to the current pointer size.
-def iPTR : ValueType<0 , 255>;
+def iPTR : ValueType<0 , 126>;
// Pseudo valuetype to represent "any type of any size".
-def Any : ValueType<0 , 256>;
+def Any : ValueType<0 , 127>;
diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h
index 46c1029f62cf3..dd730495a5f61 100644
--- a/include/llvm/CodeGen/WinEHFuncInfo.h
+++ b/include/llvm/CodeGen/WinEHFuncInfo.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/IR/Instructions.h"
namespace llvm {
class AllocaInst;
@@ -108,6 +109,7 @@ struct WinEHFuncInfo {
int EHRegNodeFrameIndex = INT_MAX;
int EHRegNodeEndOffset = INT_MAX;
+ int EHGuardFrameIndex = INT_MAX;
int SEHSetFrameOffset = INT_MAX;
WinEHFuncInfo();