42 bool Has64BitPointers;
47 void postMerge(
unsigned AggregateSize,
Class &
Lo,
Class &
Hi)
const;
50 bool IsNamedArg,
bool IsRegCall =
false)
const;
52 const Type *getIntegerTypeAtOffset(
const Type *IRType,
unsigned IROffset,
54 unsigned SourceOffset,
55 bool InMemory =
false)
const;
57 const Type *getSSETypeAtOffset(
const Type *ABIType,
unsigned ABIOffset,
59 unsigned SourceOffset)
const;
60 bool isIllegalVectorType(
const Type *Ty)
const;
61 bool containsMatrixField(
const RecordType *RT)
const;
64 ArgInfo getIndirectReturnResult(
const Type *Ty)
const;
65 const Type *getFPTypeAtOffset(
const Type *Ty,
unsigned Offset)
const;
67 const Type *getByteVectorType(
const Type *Ty)
const;
70 ArgInfo getIndirectResult(
const Type *Ty,
unsigned FreeIntRegs)
const;
72 ArgInfo classifyReturnType(
const Type *RetTy)
const;
74 ArgInfo classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
75 unsigned &NeededInt,
unsigned &NeededSse,
76 bool IsNamedArg,
bool IsRegCall =
false)
const;
82 Has64BitPointers(Has64BitPtrs), X86CompatInfo(Compat) {}
102 if (Fields.
empty()) {
106 const Type *StorageType =
nullptr;
108 for (
const auto &
Field : Fields) {
109 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
110 Field.BitFieldWidth == 0) {
117 StorageType = FieldType;
132 (FieldType->getAlignment() == StorageType->
getAlignment() &&
135 StorageType = FieldType;
141void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
198 "Invalid accumulated classification during merge.");
219bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
220 for (
const auto &
Field : RT->getFields()) {
224 if (AT->isMatrixType())
230 if (containsMatrixField(NestedRT))
236void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
237 Class &
Hi,
bool IsNamedArg,
238 bool IsRegCall)
const {
240 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
249 auto BitWidth =
IT->getSizeInBits().getFixedValue();
263 const auto *FltSem = FT->getSemantics();
281 if (
T->isPointer()) {
287 if (MPT->isFunctionPointer()) {
288 if (Has64BitPointers) {
291 uint64_t EbFuncPtr = OffsetBase / 64;
292 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
293 if (EbFuncPtr != EbThisAdj) {
306 assert(VT->isFixedLength() &&
"x86-64 has no scalable vectors");
322 }
else if (
Size == 64) {
333 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
345 if (OffsetBase && OffsetBase != 64)
347 }
else if (
Size == 128 ||
350 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
353 ElemBits == 128 && !
IT->isBitInt())
384 else if (
Size <= 128)
387 const auto *FltSem = EFT->getSemantics();
406 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
418 if (AT->isMatrixType())
428 if (!IsRegCall &&
Size > 512)
437 if (OffsetBase % ElemAlign)
444 uint64_t ArraySize = AT->getNumElements();
456 Class FieldLo, FieldHi;
457 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
458 Lo = merge(
Lo, FieldLo);
459 Hi = merge(
Hi, FieldHi);
471 if (containsMatrixField(RT)) {
488 if (RT->hasFlexibleArrayMember())
495 if (RT->isCXXRecord()) {
496 for (
const auto &
Base : RT->getBaseClasses()) {
503 Class FieldLo, FieldHi;
505 classify(
Base.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
506 Lo = merge(
Lo, FieldLo);
507 Hi = merge(
Hi, FieldHi);
510 (
Size > 128 && (
Size !=
Base.FieldType->getABISizeInBits() ||
524 for (
const auto &
Field : RT->getFields()) {
532 ?
Field.BitFieldWidth == 0
533 :
Field.IsUnnamedBitfield))
544 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
545 if (!BitField && IsInMemory) {
551 Class FieldLo, FieldHi;
559 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
567 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
570 Lo = merge(
Lo, FieldLo);
571 Hi = merge(
Hi, FieldHi);
584X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
585 unsigned &NeededInt,
unsigned &NeededSSE,
586 bool IsNamedArg,
bool IsRegCall)
const {
591 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
599 const Type *ResType =
nullptr;
608 "Unknown missing lo part");
620 return getIndirectResult(Ty, FreeIntRegs);
633 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
637 if (
Hi ==
NoClass && ResType->isInteger()) {
642 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
653 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
658 const Type *HighPart =
nullptr;
674 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
685 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
695 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
696 ResType = getByteVectorType(Ty);
704 ResType = createPairType(ResType, HighPart);
709ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
714 classify(RetTy, 0,
Lo,
Hi,
true);
720 const Type *ResType =
nullptr;
728 "Unknown missing lo part");
737 return getIndirectReturnResult(RetTy);
742 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
745 if (
Hi ==
NoClass && ResType->isInteger()) {
751 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
760 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
775 const Type *X87Type =
777 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
784 const Type *HighPart =
nullptr;
797 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
803 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
814 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
815 ResType = getByteVectorType(RetTy);
826 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
837 ResType = createPairType(ResType, HighPart);
847const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
854 llvm::Align HiAlign =
Hi->getAlignment();
855 unsigned HiStart =
alignTo(LoSize, HiAlign);
857 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
863 const Type *AdjustedLo =
Lo;
878 else if (
Lo->isInteger() ||
Lo->isPointer())
879 AdjustedLo =
TB.getIntegerType(64,
Align(8),
false);
881 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
882 "Invalid/unknown low type in pair");
883 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
884 HiStart =
alignTo(AdjustedLoSize, HiAlign);
888 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
891 assert((8 * 8) == Fields[1].OffsetInBits &&
892 "High part must be at offset 8 bytes");
895 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
903 unsigned TySize = Ty->getABISizeInBits();
904 if (TySize <= StartBit)
909 const Type *EltTy = AT->getElementType();
912 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
913 unsigned EltOffset =
I * EltSize;
914 if (EltOffset >= EndBit)
917 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
928 if (RT->isCXXRecord()) {
929 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
931 if (
Base.OffsetInBits >= EndBit)
935 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
937 EndBit -
Base.OffsetInBits))
942 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
944 if (
Field.OffsetInBits >= EndBit)
947 unsigned FieldStart =
948 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
950 EndBit -
Field.OffsetInBits))
960const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
962 const Type *SourceTy,
963 unsigned SourceOffset,
964 bool InMemory)
const {
966 const Type *WorkingType = ABIType;
967 if (InMemory && ABIType->isInteger()) {
969 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
971 unsigned WidenedBitWidth = OriginalBitWidth;
972 if (OriginalBitWidth <= 8) {
978 if (WidenedBitWidth != OriginalBitWidth) {
979 WorkingType =
TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
985 if (InMemory &&
ABIType->isVector()) {
988 if (
IT &&
IT->isBool())
989 WorkingType =
TB.getIntegerType(
990 std::max<uint64_t>(VT->getNumElements().getFixedValue(), 8),
991 ABIType->getAlignment(),
false);
995 if (ABIOffset == 0) {
1000 if ((WorkingType->isPointer() && Has64BitPointers) ||
1001 (WorkingType->isInteger() &&
1011 if ((WorkingType->isInteger() &&
1016 (WorkingType->isPointer() && !Has64BitPointers)) {
1018 unsigned BitWidth = WorkingType->isPointer()
1023 SourceOffset * 8 + 64))
1029 if (RTy->isUnion()) {
1032 if (ABIOffset * 8 < ReducedType->getABISizeInBits())
1033 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1034 SourceOffset,
true);
1039 SourceOffset * 8 + 64))
1040 return TB.getIntegerType(8,
Align(1),
false);
1041 unsigned RemainingBytes =
1043 return TB.getIntegerType(std::min(RemainingBytes, 8U) * 8,
Align(1),
1047 if (
const FieldInfo *Element =
1048 RTy->getElementContainingOffset(ABIOffset * 8)) {
1050 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1051 return getIntegerTypeAtOffset(Element->FieldType,
1052 ABIOffset - ElementOffsetBytes, SourceTy,
1053 SourceOffset,
true);
1058 const Type *EltTy = ATy->getElementType();
1059 unsigned EltSize = EltTy->getABISizeInBits() / 8;
1061 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1062 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1063 SourceOffset,
true);
1074 unsigned TySizeInBytes =
llvm::divideCeil(SourceTy->getABISizeInBits(), 8);
1075 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1076 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1077 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1081const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1084 if (
Offset == 0 && Ty->isFloat())
1089 unsigned ElementSize =
ElementType->getABISizeInBits() / 8;
1098 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1099 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1100 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1106 const Type *EltTy = AT->getElementType();
1107 unsigned EltSize = EltTy->getABISizeInBits() / 8;
1110 unsigned EltIndex =
Offset / EltSize;
1112 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1130const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1132 const Type *SourceTy,
1133 unsigned SourceOffset)
const {
1136 if (RTy->isUnion()) {
1139 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1145 auto Is16bitFpTy = [](
const Type *
T) {
1151 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1156 unsigned SourceSize = (SourceTy->getABISizeInBits() / 8) - SourceOffset;
1159 const Type *
T1 =
nullptr;
1160 unsigned T0Size = T0->getABISizeInBits() / 8;
1161 if (SourceSize > T0Size)
1162 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1164 if (
T1 ==
nullptr) {
1165 if (Is16bitFpTy(T0) && SourceSize > 4)
1166 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1176 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1177 const Type *T2 =
nullptr;
1179 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1186 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1196const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1207 VT->getElementType()->isInteger() &&
1209 unsigned Size = VT->getABISizeInBits();
1210 return TB.getVectorType(
TB.getIntegerType(64,
Align(8),
false),
1222 unsigned Size = Ty->getABISizeInBits();
1229bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1239 const Type *EltTy = VecTy->getElementType();
1242 if (IntTy->getSizeInBits().getFixedValue() == 128 && !IntTy->isBitInt())
1249ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1250 unsigned FreeIntRegs)
const {
1274 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1297 if (FreeIntRegs == 0) {
1302 if (AlignVal == 8 &&
Size <= 64) {
1304 TB.getIntegerType(
Size, llvm::Align(8),
false);
1312ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1316 if (IntTy->isBitInt())
1327void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1333 switch (CallingConv) {
1338 "calling convention not supported by the LLVMABI X86_64 classifier");
1341 unsigned FreeIntRegs = 6;
1342 unsigned FreeSSERegs = 8;
1343 unsigned NeededInt = 0, NeededSSE = 0;
1346 const Type *RetTy = FI.getReturnType();
1347 FI.getReturnInfo() = classifyReturnType(RetTy);
1350 if (FI.getReturnInfo().isIndirect())
1353 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1356 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1357 bool IsNamedArg = ArgNo < NumRequiredArgs;
1358 const Type *ArgTy =
IT->ABIType;
1362 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1369 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1370 FreeIntRegs -= NeededInt;
1371 FreeSSERegs -= NeededSSE;
1372 AI.setNeededRegs(NeededInt, NeededSSE);
1377 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1382std::unique_ptr<TargetInfo>
1385 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 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 ...
static ArgInfo getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt, bool CanBeFlattened=true)
const fltSemantics * getSemantics() const
ArrayRef< FieldInfo > getFields() const
bool isTransparentUnion() const
LLVM_ABI const Type * isSingleElementStruct(const Type *Ty) const
Returns the scalar a single-element struct reduces to, else null.
virtual unsigned getAllocaAddrSpace() const
Address space in which indirect arguments are allocated (the target's alloca/stack space).
LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const
TargetInfo(TypeBuilder &Builder)
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 ArgInfo getNaturalAlignIndirect(const Type *Ty, unsigned AddrSpace, bool ByVal=true) const
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
LLVM_ABI uint64_t getABISizeInBits() const
Returns the size in bits that the source language gives this type, including any padding.
Align getAlignment() const
X86_64TargetInfo(TypeBuilder &TypeBuilder, X86AVXABILevel AVXABILevel, bool Has64BitPtrs, const X86ABICompatInfo &Compat)
bool has64BitPointers() const
const X86ABICompatInfo & getX86ABICompatInfo() const
const ABICompatInfo & getABICompatInfo() const override
Return this target's ABI compatibility flags.
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.
LLVM_ABI std::unique_ptr< TargetInfo > createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, bool Has64BitPointers, const X86ABICompatInfo &Compat)
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)
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 ABI compatibility behaviour that applies to every target.
Flags controlling X86-specific ABI compatibility behaviour.