41 uint64_t NumBits =
IT->getSizeInBits().getFixedValue();
45 std::max<uint64_t>(8, std::min<uint64_t>(64,
llvm::bit_ceil(NumBits)));
56 if (Width & (Width - 1))
69 return Ty->getSizeInBits().getFixedValue();
79 bool Has64BitPointers;
83 void postMerge(
unsigned AggregateSize,
Class &
Lo,
Class &
Hi)
const;
86 bool IsNamedArg,
bool IsRegCall =
false)
const;
88 const Type *getIntegerTypeAtOffset(
const Type *IRType,
unsigned IROffset,
90 unsigned SourceOffset,
91 bool InMemory =
false)
const;
93 const Type *getSSETypeAtOffset(
const Type *ABIType,
unsigned ABIOffset,
95 unsigned SourceOffset)
const;
96 bool isIllegalVectorType(
const Type *Ty)
const;
97 bool containsMatrixField(
const RecordType *RT)
const;
100 ArgInfo getIndirectReturnResult(
const Type *Ty)
const;
101 const Type *getFPTypeAtOffset(
const Type *Ty,
unsigned Offset)
const;
103 const Type *isSingleElementStruct(
const Type *Ty)
const;
104 const Type *getByteVectorType(
const Type *Ty)
const;
107 ArgInfo getIndirectResult(
const Type *Ty,
unsigned FreeIntRegs)
const;
109 ArgInfo classifyReturnType(
const Type *RetTy)
const;
111 ArgInfo classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
112 unsigned &NeededInt,
unsigned &NeededSse,
113 bool IsNamedArg,
bool IsRegCall =
false)
const;
119 Has64BitPointers(Has64BitPtrs) {}
133 if (Fields.
empty()) {
137 const Type *StorageType =
nullptr;
139 for (
const auto &
Field : Fields) {
140 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
141 Field.BitFieldWidth == 0) {
148 StorageType = FieldType;
159 FieldType->getSizeInBits().getFixedValue()))
164 (FieldType->getAlignment() == StorageType->
getAlignment() &&
167 StorageType = FieldType;
173void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
230 "Invalid accumulated classification during merge.");
251bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
252 for (
const auto &
Field : RT->getFields()) {
256 if (AT->isMatrixType())
262 if (containsMatrixField(NestedRT))
268void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
269 Class &
Hi,
bool IsNamedArg,
270 bool IsRegCall)
const {
272 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
281 auto BitWidth =
IT->getSizeInBits().getFixedValue();
295 const auto *FltSem = FT->getSemantics();
313 if (
T->isPointer()) {
319 if (MPT->isFunctionPointer()) {
320 if (Has64BitPointers) {
323 uint64_t EbFuncPtr = OffsetBase / 64;
324 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
325 if (EbFuncPtr != EbThisAdj) {
338 auto Size = VT->getSizeInBits().getFixedValue();
353 }
else if (
Size == 64) {
364 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
376 if (OffsetBase && OffsetBase != 64)
378 }
else if (
Size == 128 ||
381 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
384 ElemBits == 128 && !
IT->isBitInt())
415 else if (
Size <= 128)
418 const auto *FltSem = EFT->getSemantics();
437 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
449 if (AT->isMatrixType())
459 if (!IsRegCall &&
Size > 512)
468 if (OffsetBase % ElemAlign)
475 uint64_t ArraySize = AT->getNumElements();
487 Class FieldLo, FieldHi;
488 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
489 Lo = merge(
Lo, FieldLo);
490 Hi = merge(
Hi, FieldHi);
502 if (containsMatrixField(RT)) {
519 if (RT->hasFlexibleArrayMember())
526 if (RT->isCXXRecord()) {
527 for (
const auto &
Base : RT->getBaseClasses()) {
530 assert(!
Base.IsVirtualBase &&
"Unexpected base class!");
537 Class FieldLo, FieldHi;
539 classify(
Base.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
540 Lo = merge(
Lo, FieldLo);
541 Hi = merge(
Hi, FieldHi);
545 (
Size !=
Base.FieldType->getSizeInBits().getFixedValue() ||
559 for (
const auto &
Field : RT->getFields()) {
563 if (BitField &&
Field.IsUnnamedBitfield)
568 Size !=
Field.FieldType->getSizeInBits().getFixedValue()) ||
575 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
576 if (!BitField && IsInMemory) {
582 Class FieldLo, FieldHi;
590 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
598 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
601 Lo = merge(
Lo, FieldLo);
602 Hi = merge(
Hi, FieldHi);
615X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
616 unsigned &NeededInt,
unsigned &NeededSSE,
617 bool IsNamedArg,
bool IsRegCall)
const {
622 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
630 const Type *ResType =
nullptr;
639 "Unknown missing lo part");
651 return getIndirectResult(Ty, FreeIntRegs);
664 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
668 if (
Hi ==
NoClass && ResType->isInteger()) {
673 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
684 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
689 const Type *HighPart =
nullptr;
705 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
716 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
726 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
727 ResType = getByteVectorType(Ty);
735 ResType = createPairType(ResType, HighPart);
740ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
745 classify(RetTy, 0,
Lo,
Hi,
true);
751 const Type *ResType =
nullptr;
759 "Unknown missing lo part");
768 return getIndirectReturnResult(RetTy);
773 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
776 if (
Hi ==
NoClass && ResType->isInteger()) {
782 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
791 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
806 const Type *X87Type =
808 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
814 const Type *HighPart =
nullptr;
827 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
833 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
844 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
845 ResType = getByteVectorType(RetTy);
856 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
867 ResType = createPairType(ResType, HighPart);
877const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
884 llvm::Align HiAlign =
Hi->getAlignment();
885 unsigned HiStart =
alignTo(LoSize, HiAlign);
887 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
893 const Type *AdjustedLo =
Lo;
908 else if (
Lo->isInteger() ||
Lo->isPointer())
909 AdjustedLo = TB.getIntegerType(64,
Align(8),
false);
911 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
912 "Invalid/unknown low type in pair");
913 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
914 HiStart =
alignTo(AdjustedLoSize, HiAlign);
918 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
921 assert((8 * 8) == Fields[1].OffsetInBits &&
922 "High part must be at offset 8 bytes");
925 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
933 unsigned TySize = Ty->getSizeInBits().getFixedValue();
934 if (TySize <= StartBit)
939 const Type *EltTy = AT->getElementType();
942 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
943 unsigned EltOffset =
I * EltSize;
944 if (EltOffset >= EndBit)
947 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
958 if (RT->isCXXRecord()) {
959 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
963 assert(!
Base.IsVirtualBase &&
"Unexpected base class!");
964 if (
Base.OffsetInBits >= EndBit)
968 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
970 EndBit -
Base.OffsetInBits))
975 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
977 if (
Field.OffsetInBits >= EndBit)
980 unsigned FieldStart =
981 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
983 EndBit -
Field.OffsetInBits))
993const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
995 const Type *SourceTy,
996 unsigned SourceOffset,
997 bool InMemory)
const {
999 const Type *WorkingType = ABIType;
1000 if (InMemory && ABIType->isInteger()) {
1002 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
1004 unsigned WidenedBitWidth = OriginalBitWidth;
1005 if (OriginalBitWidth <= 8) {
1006 WidenedBitWidth = 8;
1011 if (WidenedBitWidth != OriginalBitWidth) {
1012 WorkingType = TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
1018 if (ABIOffset == 0) {
1023 if ((WorkingType->isPointer() && Has64BitPointers) ||
1024 (WorkingType->isInteger() &&
1034 if ((WorkingType->isInteger() &&
1039 (WorkingType->isPointer() && !Has64BitPointers)) {
1041 unsigned BitWidth = WorkingType->isPointer()
1046 SourceOffset * 8 + 64))
1052 if (RTy->isUnion()) {
1055 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1056 SourceOffset,
true);
1058 if (
const FieldInfo *Element =
1059 RTy->getElementContainingOffset(ABIOffset * 8)) {
1061 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1062 return getIntegerTypeAtOffset(Element->FieldType,
1063 ABIOffset - ElementOffsetBytes, SourceTy,
1064 SourceOffset,
true);
1069 const Type *EltTy = ATy->getElementType();
1070 unsigned EltSize = EltTy->getSizeInBits() / 8;
1072 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1073 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1074 SourceOffset,
true);
1085 unsigned TySizeInBytes =
1090 alignTo(SourceTy->getSizeInBits().getFixedValue(), 64) / 8;
1092 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1093 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1094 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1098const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1101 if (
Offset == 0 && Ty->isFloat())
1106 unsigned ElementSize =
ElementType->getSizeInBits().getFixedValue() / 8;
1115 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1116 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1117 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1123 const Type *EltTy = AT->getElementType();
1124 unsigned EltSize = EltTy->getSizeInBits() / 8;
1125 unsigned EltIndex =
Offset / EltSize;
1127 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1145const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1147 const Type *SourceTy,
1148 unsigned SourceOffset)
const {
1151 if (RTy->isUnion()) {
1154 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1160 auto Is16bitFpTy = [](
const Type *
T) {
1166 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1171 unsigned SourceSize =
1172 (SourceTy->getSizeInBits().getFixedValue() / 8) - SourceOffset;
1175 const Type *
T1 =
nullptr;
1177 alignTo(T0->getSizeInBits().getFixedValue(), T0->getAlignment().value()) /
1179 if (SourceSize > T0Size)
1180 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1182 if (
T1 ==
nullptr) {
1183 if (Is16bitFpTy(T0) && SourceSize > 4)
1184 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1194 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1195 const Type *T2 =
nullptr;
1197 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1204 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1214const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1217 if (
const Type *InnerTy = isSingleElementStruct(Ty))
1225 VT->getElementType()->isInteger() &&
1227 unsigned Size = VT->getSizeInBits().getFixedValue();
1228 return TB.getVectorType(TB.getIntegerType(64,
Align(8),
false),
1240 unsigned Size = Ty->getSizeInBits().getFixedValue();
1248const Type *X86_64TargetInfo::isSingleElementStruct(
const Type *Ty)
const {
1253 if (RT->hasFlexibleArrayMember())
1256 const Type *Found =
nullptr;
1258 for (
const auto &
Base : RT->getBaseClasses()) {
1259 const Type *BaseTy =
Base.FieldType;
1262 if (!BaseRT || BaseRT->isEmpty())
1265 const Type *Elem = isSingleElementStruct(BaseTy);
1271 for (
const auto &FI : RT->getFields()) {
1275 const Type *FTy = FI.FieldType;
1278 if (AT->getNumElements() != 1)
1280 FTy = AT->getElementType();
1285 Elem = isSingleElementStruct(InnerRT);
1295 if (Found->getSizeInBits() != Ty->getSizeInBits())
1301bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1303 uint64_t Size = VecTy->getSizeInBits().getFixedValue();
1311 const Type *EltTy = VecTy->getElementType();
1314 if (IntTy->getSizeInBits().getFixedValue() == 128)
1321ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1322 unsigned FreeIntRegs)
const {
1345 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1368 if (FreeIntRegs == 0) {
1376 if (AlignVal == 8 &&
Size <= 64) {
1378 TB.getIntegerType(
Size, llvm::Align(8),
false);
1386ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1390 if (IntTy->isBitInt())
1401void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1407 switch (CallingConv) {
1412 "calling convention not supported by the LLVMABI X86_64 classifier");
1415 unsigned FreeIntRegs = 6;
1416 unsigned FreeSSERegs = 8;
1417 unsigned NeededInt = 0, NeededSSE = 0;
1420 const Type *RetTy = FI.getReturnType();
1421 FI.getReturnInfo() = classifyReturnType(RetTy);
1424 if (FI.getReturnInfo().isIndirect())
1427 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1430 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1431 bool IsNamedArg = ArgNo < NumRequiredArgs;
1432 const Type *ArgTy =
IT->ABIType;
1436 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1443 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1444 FreeIntRegs -= NeededInt;
1445 FreeSSERegs -= NeededSSE;
1449 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1454std::unique_ptr<TargetInfo>
1457 return std::make_unique<X86_64TargetInfo>(TB, AVXLevel, Has64BitPointers,
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B)
OptimizedStructLayoutField Field
FunctionLoweringInfo::StatepointRelocationRecord RecordType
Target-specific ABI information and factory functions.
static const fltSemantics & IEEEsingle()
static const fltSemantics & BFloat()
static const fltSemantics & IEEEquad()
static const fltSemantics & IEEEdouble()
static const fltSemantics & x87DoubleExtended()
static const fltSemantics & IEEEhalf()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
Helper class to encapsulate information about how a specific type should be passed to or returned fro...
static ArgInfo getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt)
static ArgInfo getIgnore()
static ArgInfo getExtend(const Type *T)
static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace=0, bool Realign=false)
Realign: the caller couldn't guarantee sufficient alignment - the callee must copy the argument to a ...
const fltSemantics * getSemantics() const
ArrayRef< FieldInfo > getFields() const
bool isTransparentUnion() const
LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty, bool ByVal=true) const
const ABICompatInfo & getABICompatInfo() const
LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const
LLVM_ABI bool maybeCommonClassifyReturnType(FunctionInfo &FI) const
Apply rules for classifying return types that are common to all targets.
LLVM_ABI bool isAggregateTypeForABI(const Type *Ty) const
LLVM_ABI const Type * useFirstFieldIfTransparentUnion(const Type *Ty) const
If Ty is a transparent union, return its first field type; otherwise return Ty unchanged.
LLVM_ABI RecordArgABI getRecordArgABI(const RecordType *RT) const
TypeBuilder manages the lifecycle of ABI types using bump pointer allocation.
Represents the ABI-specific view of a type in LLVM.
TypeSize getTypeAllocSize() const
TypeSize getSizeInBits() const
Align getAlignment() const
ElementCount getNumElements() const
const Type * getElementType() const
X86_64TargetInfo(TypeBuilder &TypeBuilder, X86AVXABILevel AVXABILevel, bool Has64BitPtrs, const ABICompatInfo &Compat)
bool has64BitPointers() const
constexpr ScalarTy getFixedValue() const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
This class provides various memory handling functions that manipulate MemoryBlock instances.
This file defines the type system for the LLVMABI library, which mirrors ABI-relevant aspects of fron...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
static uint64_t getClangTypeWidthInBits(const Type *Ty)
static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel)
X86AVXABILevel
The AVX ABI level for X86 targets.
static const Type * reduceUnionForX8664(const RecordType *UnionType, TypeBuilder &TB)
static bool bitsContainNoUserData(const Type *Ty, unsigned StartBit, unsigned EndBit)
LLVM_ABI std::unique_ptr< TargetInfo > createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, bool Has64BitPointers, const ABICompatInfo &Compat)
static uint64_t getClangVectorWidthInBits(const VectorType *VT)
static uint64_t getClangIntegerWidthInBits(const IntegerType *IT)
static bool isFloatTypeWithSemantics(const Type *Ty, const fltSemantics &Semantics)
Helper to check if a floating point type matches specific semantics.
@ RAA_Indirect
Pass it as a pointer to temporary memory.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
ElementType
The element type of an SRV or UAV resource.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Flags controlling target-specific ABI compatibility behaviour.