41 uint64_t NumBits =
IT->getSizeInBits().getFixedValue();
45 std::max<uint64_t>(8, std::min<uint64_t>(64,
llvm::bit_ceil(NumBits)));
67 return Ty->getSizeInBits().getFixedValue();
76 bool Has64BitPointers;
81 void postMerge(
unsigned AggregateSize,
Class &
Lo,
Class &
Hi)
const;
84 bool IsNamedArg,
bool IsRegCall =
false)
const;
86 const Type *getIntegerTypeAtOffset(
const Type *IRType,
unsigned IROffset,
88 unsigned SourceOffset,
89 bool InMemory =
false)
const;
91 const Type *getSSETypeAtOffset(
const Type *ABIType,
unsigned ABIOffset,
93 unsigned SourceOffset)
const;
94 bool isIllegalVectorType(
const Type *Ty)
const;
95 bool containsMatrixField(
const RecordType *RT)
const;
98 ArgInfo getIndirectReturnResult(
const Type *Ty)
const;
99 const Type *getFPTypeAtOffset(
const Type *Ty,
unsigned Offset)
const;
101 const Type *getByteVectorType(
const Type *Ty)
const;
104 ArgInfo getIndirectResult(
const Type *Ty,
unsigned FreeIntRegs)
const;
106 ArgInfo classifyReturnType(
const Type *RetTy)
const;
108 ArgInfo classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
109 unsigned &NeededInt,
unsigned &NeededSse,
110 bool IsNamedArg,
bool IsRegCall =
false)
const;
116 Has64BitPointers(Has64BitPtrs), X86CompatInfo(Compat) {}
121 return X86CompatInfo;
136 if (Fields.
empty()) {
140 const Type *StorageType =
nullptr;
142 for (
const auto &
Field : Fields) {
143 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
144 Field.BitFieldWidth == 0) {
151 StorageType = FieldType;
162 FieldType->getSizeInBits().getFixedValue()))
167 (FieldType->getAlignment() == StorageType->
getAlignment() &&
170 StorageType = FieldType;
176void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
233 "Invalid accumulated classification during merge.");
254bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
255 for (
const auto &
Field : RT->getFields()) {
259 if (AT->isMatrixType())
265 if (containsMatrixField(NestedRT))
271void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
272 Class &
Hi,
bool IsNamedArg,
273 bool IsRegCall)
const {
275 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
284 auto BitWidth =
IT->getSizeInBits().getFixedValue();
298 const auto *FltSem = FT->getSemantics();
316 if (
T->isPointer()) {
322 if (MPT->isFunctionPointer()) {
323 if (Has64BitPointers) {
326 uint64_t EbFuncPtr = OffsetBase / 64;
327 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
328 if (EbFuncPtr != EbThisAdj) {
341 auto Size = VT->getSizeInBits().getFixedValue();
356 }
else if (
Size == 64) {
367 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
379 if (OffsetBase && OffsetBase != 64)
381 }
else if (
Size == 128 ||
384 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
387 ElemBits == 128 && !
IT->isBitInt())
418 else if (
Size <= 128)
421 const auto *FltSem = EFT->getSemantics();
440 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
452 if (AT->isMatrixType())
462 if (!IsRegCall &&
Size > 512)
471 if (OffsetBase % ElemAlign)
478 uint64_t ArraySize = AT->getNumElements();
490 Class FieldLo, FieldHi;
491 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
492 Lo = merge(
Lo, FieldLo);
493 Hi = merge(
Hi, FieldHi);
505 if (containsMatrixField(RT)) {
522 if (RT->hasFlexibleArrayMember())
529 if (RT->isCXXRecord()) {
530 for (
const auto &
Base : RT->getBaseClasses()) {
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()) {
567 ?
Field.BitFieldWidth == 0
568 :
Field.IsUnnamedBitfield))
573 Size !=
Field.FieldType->getSizeInBits().getFixedValue()) ||
580 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
581 if (!BitField && IsInMemory) {
587 Class FieldLo, FieldHi;
595 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
603 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
606 Lo = merge(
Lo, FieldLo);
607 Hi = merge(
Hi, FieldHi);
620X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
621 unsigned &NeededInt,
unsigned &NeededSSE,
622 bool IsNamedArg,
bool IsRegCall)
const {
627 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
635 const Type *ResType =
nullptr;
644 "Unknown missing lo part");
656 return getIndirectResult(Ty, FreeIntRegs);
669 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
673 if (
Hi ==
NoClass && ResType->isInteger()) {
678 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
689 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
694 const Type *HighPart =
nullptr;
710 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
721 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
731 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
732 ResType = getByteVectorType(Ty);
740 ResType = createPairType(ResType, HighPart);
745ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
750 classify(RetTy, 0,
Lo,
Hi,
true);
756 const Type *ResType =
nullptr;
764 "Unknown missing lo part");
773 return getIndirectReturnResult(RetTy);
778 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
781 if (
Hi ==
NoClass && ResType->isInteger()) {
787 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
796 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
811 const Type *X87Type =
813 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
820 const Type *HighPart =
nullptr;
833 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
839 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
850 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
851 ResType = getByteVectorType(RetTy);
862 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
873 ResType = createPairType(ResType, HighPart);
883const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
890 llvm::Align HiAlign =
Hi->getAlignment();
891 unsigned HiStart =
alignTo(LoSize, HiAlign);
893 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
899 const Type *AdjustedLo =
Lo;
914 else if (
Lo->isInteger() ||
Lo->isPointer())
915 AdjustedLo =
TB.getIntegerType(64,
Align(8),
false);
917 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
918 "Invalid/unknown low type in pair");
919 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
920 HiStart =
alignTo(AdjustedLoSize, HiAlign);
924 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
927 assert((8 * 8) == Fields[1].OffsetInBits &&
928 "High part must be at offset 8 bytes");
931 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
939 unsigned TySize = Ty->getSizeInBits().getFixedValue();
940 if (TySize <= StartBit)
945 const Type *EltTy = AT->getElementType();
948 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
949 unsigned EltOffset =
I * EltSize;
950 if (EltOffset >= EndBit)
953 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
964 if (RT->isCXXRecord()) {
965 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
967 if (
Base.OffsetInBits >= EndBit)
971 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
973 EndBit -
Base.OffsetInBits))
978 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
980 if (
Field.OffsetInBits >= EndBit)
983 unsigned FieldStart =
984 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
986 EndBit -
Field.OffsetInBits))
996const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
998 const Type *SourceTy,
999 unsigned SourceOffset,
1000 bool InMemory)
const {
1002 const Type *WorkingType = ABIType;
1003 if (InMemory && ABIType->isInteger()) {
1005 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
1007 unsigned WidenedBitWidth = OriginalBitWidth;
1008 if (OriginalBitWidth <= 8) {
1009 WidenedBitWidth = 8;
1014 if (WidenedBitWidth != OriginalBitWidth) {
1015 WorkingType =
TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
1021 if (ABIOffset == 0) {
1026 if ((WorkingType->isPointer() && Has64BitPointers) ||
1027 (WorkingType->isInteger() &&
1037 if ((WorkingType->isInteger() &&
1042 (WorkingType->isPointer() && !Has64BitPointers)) {
1044 unsigned BitWidth = WorkingType->isPointer()
1049 SourceOffset * 8 + 64))
1055 if (RTy->isUnion()) {
1058 if (ABIOffset * 8 < ReducedType->getSizeInBits().getFixedValue())
1059 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1060 SourceOffset,
true);
1065 SourceOffset * 8 + 64))
1066 return TB.getIntegerType(8,
Align(1),
false);
1067 unsigned RemainingBytes =
1070 return TB.getIntegerType(std::min(RemainingBytes, 8U) * 8,
Align(1),
1074 if (
const FieldInfo *Element =
1075 RTy->getElementContainingOffset(ABIOffset * 8)) {
1077 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1078 return getIntegerTypeAtOffset(Element->FieldType,
1079 ABIOffset - ElementOffsetBytes, SourceTy,
1080 SourceOffset,
true);
1085 const Type *EltTy = ATy->getElementType();
1086 unsigned EltSize = EltTy->getSizeInBits() / 8;
1088 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1089 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1090 SourceOffset,
true);
1101 unsigned TySizeInBytes =
1106 alignTo(SourceTy->getSizeInBits().getFixedValue(), 64) / 8;
1108 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1109 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1110 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1114const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1117 if (
Offset == 0 && Ty->isFloat())
1122 unsigned ElementSize =
ElementType->getSizeInBits().getFixedValue() / 8;
1131 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1132 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1133 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1139 const Type *EltTy = AT->getElementType();
1140 unsigned EltSize = EltTy->getSizeInBits() / 8;
1141 unsigned EltIndex =
Offset / EltSize;
1143 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1161const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1163 const Type *SourceTy,
1164 unsigned SourceOffset)
const {
1167 if (RTy->isUnion()) {
1170 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1176 auto Is16bitFpTy = [](
const Type *
T) {
1182 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1187 unsigned SourceSize =
1188 (SourceTy->getSizeInBits().getFixedValue() / 8) - SourceOffset;
1191 const Type *
T1 =
nullptr;
1193 alignTo(T0->getSizeInBits().getFixedValue(), T0->getAlignment().value()) /
1195 if (SourceSize > T0Size)
1196 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1198 if (
T1 ==
nullptr) {
1199 if (Is16bitFpTy(T0) && SourceSize > 4)
1200 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1210 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1211 const Type *T2 =
nullptr;
1213 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1220 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1230const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1241 VT->getElementType()->isInteger() &&
1243 unsigned Size = VT->getSizeInBits().getFixedValue();
1244 return TB.getVectorType(
TB.getIntegerType(64,
Align(8),
false),
1256 unsigned Size = Ty->getSizeInBits().getFixedValue();
1263bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1265 uint64_t Size = VecTy->getSizeInBits().getFixedValue();
1273 const Type *EltTy = VecTy->getElementType();
1276 if (IntTy->getSizeInBits().getFixedValue() == 128)
1283ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1284 unsigned FreeIntRegs)
const {
1308 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1331 if (FreeIntRegs == 0) {
1339 if (AlignVal == 8 &&
Size <= 64) {
1341 TB.getIntegerType(
Size, llvm::Align(8),
false);
1349ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1353 if (IntTy->isBitInt())
1364void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1370 switch (CallingConv) {
1375 "calling convention not supported by the LLVMABI X86_64 classifier");
1378 unsigned FreeIntRegs = 6;
1379 unsigned FreeSSERegs = 8;
1380 unsigned NeededInt = 0, NeededSSE = 0;
1383 const Type *RetTy = FI.getReturnType();
1384 FI.getReturnInfo() = classifyReturnType(RetTy);
1387 if (FI.getReturnInfo().isIndirect())
1390 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1393 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1394 bool IsNamedArg = ArgNo < NumRequiredArgs;
1395 const Type *ArgTy =
IT->ABIType;
1399 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1406 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1407 FreeIntRegs -= NeededInt;
1408 FreeSSERegs -= NeededSSE;
1409 AI.setNeededRegs(NeededInt, NeededSSE);
1414 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1419std::unique_ptr<TargetInfo>
1422 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
Align getAlignment() const
ElementCount getNumElements() const
const Type * getElementType() 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.
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.
LLVM_ABI std::unique_ptr< TargetInfo > createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, bool Has64BitPointers, const X86ABICompatInfo &Compat)
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)
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 ABI compatibility behaviour that applies to every target.
Flags controlling X86-specific ABI compatibility behaviour.