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) {}
130 if (Fields.
empty()) {
134 const Type *StorageType =
nullptr;
136 for (
const auto &
Field : Fields) {
137 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
138 Field.BitFieldWidth == 0) {
145 StorageType = FieldType;
151 (FieldType->getAlignment() == StorageType->
getAlignment() &&
154 StorageType = FieldType;
160void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
217 "Invalid accumulated classification during merge.");
238bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
239 for (
const auto &
Field : RT->getFields()) {
243 if (AT->isMatrixType())
249 if (containsMatrixField(NestedRT))
255void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
256 Class &
Hi,
bool IsNamedArg,
257 bool IsRegCall)
const {
259 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
268 auto BitWidth =
IT->getSizeInBits().getFixedValue();
282 const auto *FltSem = FT->getSemantics();
300 if (
T->isPointer()) {
306 if (MPT->isFunctionPointer()) {
307 if (Has64BitPointers) {
310 uint64_t EbFuncPtr = OffsetBase / 64;
311 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
312 if (EbFuncPtr != EbThisAdj) {
325 auto Size = VT->getSizeInBits().getFixedValue();
340 }
else if (
Size == 64) {
351 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
363 if (OffsetBase && OffsetBase != 64)
365 }
else if (
Size == 128 ||
368 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
371 ElemBits == 128 && !
IT->isBitInt())
402 else if (
Size <= 128)
405 const auto *FltSem = EFT->getSemantics();
424 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
436 if (AT->isMatrixType())
446 if (!IsRegCall &&
Size > 512)
455 if (OffsetBase % ElemAlign)
462 uint64_t ArraySize = AT->getNumElements();
474 Class FieldLo, FieldHi;
475 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
476 Lo = merge(
Lo, FieldLo);
477 Hi = merge(
Hi, FieldHi);
489 if (containsMatrixField(RT)) {
506 if (RT->hasFlexibleArrayMember())
513 if (RT->isCXXRecord()) {
514 for (
const auto &
Base : RT->getBaseClasses()) {
521 Class FieldLo, FieldHi;
523 classify(
Base.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
524 Lo = merge(
Lo, FieldLo);
525 Hi = merge(
Hi, FieldHi);
529 (
Size !=
Base.FieldType->getSizeInBits().getFixedValue() ||
543 for (
const auto &
Field : RT->getFields()) {
547 if (BitField &&
Field.IsUnnamedBitfield)
552 Size !=
Field.FieldType->getSizeInBits().getFixedValue()) ||
559 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
560 if (!BitField && IsInMemory) {
566 Class FieldLo, FieldHi;
574 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
582 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
585 Lo = merge(
Lo, FieldLo);
586 Hi = merge(
Hi, FieldHi);
599X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
600 unsigned &NeededInt,
unsigned &NeededSSE,
601 bool IsNamedArg,
bool IsRegCall)
const {
606 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
614 const Type *ResType =
nullptr;
623 "Unknown missing lo part");
635 return getIndirectResult(Ty, FreeIntRegs);
648 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
652 if (
Hi ==
NoClass && ResType->isInteger()) {
657 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
668 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
673 const Type *HighPart =
nullptr;
689 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
700 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
710 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
711 ResType = getByteVectorType(Ty);
719 ResType = createPairType(ResType, HighPart);
724ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
729 classify(RetTy, 0,
Lo,
Hi,
true);
735 const Type *ResType =
nullptr;
743 "Unknown missing lo part");
752 return getIndirectReturnResult(RetTy);
757 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
760 if (
Hi ==
NoClass && ResType->isInteger()) {
766 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
775 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
790 const Type *X87Type =
792 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
798 const Type *HighPart =
nullptr;
811 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
817 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
828 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
829 ResType = getByteVectorType(RetTy);
840 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
851 ResType = createPairType(ResType, HighPart);
861const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
868 llvm::Align HiAlign =
Hi->getAlignment();
869 unsigned HiStart =
alignTo(LoSize, HiAlign);
871 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
877 const Type *AdjustedLo =
Lo;
892 else if (
Lo->isInteger() ||
Lo->isPointer())
893 AdjustedLo = TB.getIntegerType(64,
Align(8),
false);
895 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
896 "Invalid/unknown low type in pair");
897 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
898 HiStart =
alignTo(AdjustedLoSize, HiAlign);
902 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
905 assert((8 * 8) == Fields[1].OffsetInBits &&
906 "High part must be at offset 8 bytes");
909 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
917 unsigned TySize = Ty->getSizeInBits().getFixedValue();
918 if (TySize <= StartBit)
923 const Type *EltTy = AT->getElementType();
926 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
927 unsigned EltOffset =
I * EltSize;
928 if (EltOffset >= EndBit)
931 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
942 if (RT->isCXXRecord()) {
943 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
945 if (
Base.OffsetInBits >= EndBit)
949 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
951 EndBit -
Base.OffsetInBits))
956 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
958 if (
Field.OffsetInBits >= EndBit)
961 unsigned FieldStart =
962 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
964 EndBit -
Field.OffsetInBits))
974const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
976 const Type *SourceTy,
977 unsigned SourceOffset,
978 bool InMemory)
const {
980 const Type *WorkingType = ABIType;
981 if (InMemory && ABIType->isInteger()) {
983 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
985 unsigned WidenedBitWidth = OriginalBitWidth;
986 if (OriginalBitWidth <= 8) {
992 if (WidenedBitWidth != OriginalBitWidth) {
993 WorkingType = TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
999 if (ABIOffset == 0) {
1004 if ((WorkingType->isPointer() && Has64BitPointers) ||
1005 (WorkingType->isInteger() &&
1015 if ((WorkingType->isInteger() &&
1020 (WorkingType->isPointer() && !Has64BitPointers)) {
1022 unsigned BitWidth = WorkingType->isPointer()
1027 SourceOffset * 8 + 64))
1033 if (RTy->isUnion()) {
1036 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1037 SourceOffset,
true);
1039 if (
const FieldInfo *Element =
1040 RTy->getElementContainingOffset(ABIOffset * 8)) {
1042 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1043 return getIntegerTypeAtOffset(Element->FieldType,
1044 ABIOffset - ElementOffsetBytes, SourceTy,
1045 SourceOffset,
true);
1050 const Type *EltTy = ATy->getElementType();
1051 unsigned EltSize = EltTy->getSizeInBits() / 8;
1053 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1054 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1055 SourceOffset,
true);
1066 unsigned TySizeInBytes =
1071 alignTo(SourceTy->getSizeInBits().getFixedValue(), 64) / 8;
1073 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1074 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1075 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1079const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1082 if (
Offset == 0 && Ty->isFloat())
1087 unsigned ElementSize =
ElementType->getSizeInBits().getFixedValue() / 8;
1096 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1097 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1098 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1104 const Type *EltTy = AT->getElementType();
1105 unsigned EltSize = EltTy->getSizeInBits() / 8;
1106 unsigned EltIndex =
Offset / EltSize;
1108 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1126const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1128 const Type *SourceTy,
1129 unsigned SourceOffset)
const {
1132 if (RTy->isUnion()) {
1135 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1141 auto Is16bitFpTy = [](
const Type *
T) {
1147 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1152 unsigned SourceSize =
1153 (SourceTy->getSizeInBits().getFixedValue() / 8) - SourceOffset;
1156 const Type *
T1 =
nullptr;
1158 alignTo(T0->getSizeInBits().getFixedValue(), T0->getAlignment().value()) /
1160 if (SourceSize > T0Size)
1161 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1163 if (
T1 ==
nullptr) {
1164 if (Is16bitFpTy(T0) && SourceSize > 4)
1165 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1175 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1176 const Type *T2 =
nullptr;
1178 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1185 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1195const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1198 if (
const Type *InnerTy = isSingleElementStruct(Ty))
1206 VT->getElementType()->isInteger() &&
1208 unsigned Size = VT->getSizeInBits().getFixedValue();
1209 return TB.getVectorType(TB.getIntegerType(64,
Align(8),
false),
1221 unsigned Size = Ty->getSizeInBits().getFixedValue();
1229const Type *X86_64TargetInfo::isSingleElementStruct(
const Type *Ty)
const {
1234 if (RT->hasFlexibleArrayMember())
1237 const Type *Found =
nullptr;
1239 for (
const auto &
Base : RT->getBaseClasses()) {
1240 const Type *BaseTy =
Base.FieldType;
1243 if (!BaseRT || BaseRT->isEmpty())
1246 const Type *Elem = isSingleElementStruct(BaseTy);
1252 for (
const auto &FI : RT->getFields()) {
1256 const Type *FTy = FI.FieldType;
1259 if (AT->getNumElements() != 1)
1261 FTy = AT->getElementType();
1266 Elem = isSingleElementStruct(InnerRT);
1276 if (Found->getSizeInBits() != Ty->getSizeInBits())
1282bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1284 uint64_t Size = VecTy->getSizeInBits().getFixedValue();
1292 const Type *EltTy = VecTy->getElementType();
1295 if (IntTy->getSizeInBits().getFixedValue() == 128)
1302ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1303 unsigned FreeIntRegs)
const {
1326 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1349 if (FreeIntRegs == 0) {
1357 if (AlignVal == 8 &&
Size <= 64) {
1359 TB.getIntegerType(
Size, llvm::Align(8),
false);
1367ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1371 if (IntTy->isBitInt())
1382void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1388 switch (CallingConv) {
1393 "calling convention not supported by the LLVMABI X86_64 classifier");
1396 unsigned FreeIntRegs = 6;
1397 unsigned FreeSSERegs = 8;
1398 unsigned NeededInt = 0, NeededSSE = 0;
1401 const Type *RetTy = FI.getReturnType();
1402 FI.getReturnInfo() = classifyReturnType(RetTy);
1405 if (FI.getReturnInfo().isIndirect())
1408 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1411 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1412 bool IsNamedArg = ArgNo < NumRequiredArgs;
1413 const Type *ArgTy =
IT->ABIType;
1417 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1424 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1425 FreeIntRegs -= NeededInt;
1426 FreeSSERegs -= NeededSSE;
1430 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1435std::unique_ptr<TargetInfo>
1438 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.