diff options
author | Phoebe Wang <phoebe.wang@intel.com> | 2022-03-29 09:41:31 +0800 |
---|---|---|
committer | Phoebe Wang <phoebe.wang@intel.com> | 2022-03-29 11:29:57 +0800 |
commit | cd26190a10fceb6e1472fabcd9e1736f62f078c4 (patch) | |
tree | 7bf091b5aae7eaa015321dbe801713a0f839e7a0 /clang/lib/CodeGen/TargetInfo.cpp | |
parent | 48e251b1d60c872e0ce8ede6c030b053ebaa5ee9 (diff) | |
download | llvm-cd26190a10fceb6e1472fabcd9e1736f62f078c4.zip llvm-cd26190a10fceb6e1472fabcd9e1736f62f078c4.tar.gz llvm-cd26190a10fceb6e1472fabcd9e1736f62f078c4.tar.bz2 |
[X86][regcall] Support passing / returning structures
Currently, the regcall calling conversion in Clang doesn't match with
ICC when passing / returning structures. https://godbolt.org/z/axxKMKrW7
This patch tries to fix the problem to match with ICC.
Reviewed By: LuoYuanke
Differential Revision: https://reviews.llvm.org/D122104
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 77 |
1 files changed, 50 insertions, 27 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 908f42a..e1df6f5 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2297,6 +2297,8 @@ class X86_64ABIInfo : public SwiftABIInfo { /// \param isNamedArg - Whether the argument in question is a "named" /// argument, as used in AMD64-ABI 3.5.7. /// + /// \param IsRegCall - Whether the calling conversion is regcall. + /// /// If a word is unused its result will be NoClass; if a type should /// be passed in Memory then at least the classification of \arg Lo /// will be Memory. @@ -2306,7 +2308,7 @@ class X86_64ABIInfo : public SwiftABIInfo { /// If the \arg Lo class is ComplexX87, then the \arg Hi class will /// also be ComplexX87. void classify(QualType T, uint64_t OffsetBase, Class &Lo, Class &Hi, - bool isNamedArg) const; + bool isNamedArg, bool IsRegCall = false) const; llvm::Type *GetByteVectorType(QualType Ty) const; llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType, @@ -2331,13 +2333,16 @@ class X86_64ABIInfo : public SwiftABIInfo { ABIArgInfo classifyArgumentType(QualType Ty, unsigned freeIntRegs, unsigned &neededInt, unsigned &neededSSE, - bool isNamedArg) const; + bool isNamedArg, + bool IsRegCall = false) const; ABIArgInfo classifyRegCallStructType(QualType Ty, unsigned &NeededInt, - unsigned &NeededSSE) const; + unsigned &NeededSSE, + unsigned &MaxVectorWidth) const; ABIArgInfo classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, - unsigned &NeededSSE) const; + unsigned &NeededSSE, + unsigned &MaxVectorWidth) const; bool IsIllegalVectorType(QualType Ty) const; @@ -2832,8 +2837,8 @@ X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum, Class Field) { return SSE; } -void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, - Class &Lo, Class &Hi, bool isNamedArg) const { +void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, + Class &Hi, bool isNamedArg, bool IsRegCall) const { // FIXME: This code can be simplified by introducing a simple value class for // Class pairs with appropriate constructor methods for the various // situations. @@ -3031,7 +3036,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger // than eight eightbytes, ..., it has class MEMORY. - if (Size > 512) + // regcall ABI doesn't have limitation to an object. The only limitation + // is the free registers, which will be checked in computeInfo. + if (!IsRegCall && Size > 512) return; // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned @@ -3738,15 +3745,14 @@ classifyReturnType(QualType RetTy) const { return ABIArgInfo::getDirect(ResType); } -ABIArgInfo X86_64ABIInfo::classifyArgumentType( - QualType Ty, unsigned freeIntRegs, unsigned &neededInt, unsigned &neededSSE, - bool isNamedArg) - const -{ +ABIArgInfo +X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, + unsigned &neededInt, unsigned &neededSSE, + bool isNamedArg, bool IsRegCall) const { Ty = useFirstFieldIfTransparentUnion(Ty); X86_64ABIInfo::Class Lo, Hi; - classify(Ty, 0, Lo, Hi, isNamedArg); + classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall); // Check some invariants. // FIXME: Enforce these by construction. @@ -3869,7 +3875,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType( ABIArgInfo X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, - unsigned &NeededSSE) const { + unsigned &NeededSSE, + unsigned &MaxVectorWidth) const { auto RT = Ty->getAs<RecordType>(); assert(RT && "classifyRegCallStructType only valid with struct types"); @@ -3884,7 +3891,8 @@ X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, } for (const auto &I : CXXRD->bases()) - if (classifyRegCallStructTypeImpl(I.getType(), NeededInt, NeededSSE) + if (classifyRegCallStructTypeImpl(I.getType(), NeededInt, NeededSSE, + MaxVectorWidth) .isIndirect()) { NeededInt = NeededSSE = 0; return getIndirectReturnResult(Ty); @@ -3893,20 +3901,27 @@ X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, // Sum up members for (const auto *FD : RT->getDecl()->fields()) { - if (FD->getType()->isRecordType() && !FD->getType()->isUnionType()) { - if (classifyRegCallStructTypeImpl(FD->getType(), NeededInt, NeededSSE) + QualType MTy = FD->getType(); + if (MTy->isRecordType() && !MTy->isUnionType()) { + if (classifyRegCallStructTypeImpl(MTy, NeededInt, NeededSSE, + MaxVectorWidth) .isIndirect()) { NeededInt = NeededSSE = 0; return getIndirectReturnResult(Ty); } } else { unsigned LocalNeededInt, LocalNeededSSE; - if (classifyArgumentType(FD->getType(), UINT_MAX, LocalNeededInt, - LocalNeededSSE, true) + if (classifyArgumentType(MTy, UINT_MAX, LocalNeededInt, LocalNeededSSE, + true, true) .isIndirect()) { NeededInt = NeededSSE = 0; return getIndirectReturnResult(Ty); } + if (const auto *AT = getContext().getAsConstantArrayType(MTy)) + MTy = AT->getElementType(); + if (const auto *VT = MTy->getAs<VectorType>()) + if (getContext().getTypeSize(VT) > MaxVectorWidth) + MaxVectorWidth = getContext().getTypeSize(VT); NeededInt += LocalNeededInt; NeededSSE += LocalNeededSSE; } @@ -3915,14 +3930,17 @@ X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, return ABIArgInfo::getDirect(); } -ABIArgInfo X86_64ABIInfo::classifyRegCallStructType(QualType Ty, - unsigned &NeededInt, - unsigned &NeededSSE) const { +ABIArgInfo +X86_64ABIInfo::classifyRegCallStructType(QualType Ty, unsigned &NeededInt, + unsigned &NeededSSE, + unsigned &MaxVectorWidth) const { NeededInt = 0; NeededSSE = 0; + MaxVectorWidth = 0; - return classifyRegCallStructTypeImpl(Ty, NeededInt, NeededSSE); + return classifyRegCallStructTypeImpl(Ty, NeededInt, NeededSSE, + MaxVectorWidth); } void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { @@ -3942,13 +3960,13 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { // Keep track of the number of assigned registers. unsigned FreeIntRegs = IsRegCall ? 11 : 6; unsigned FreeSSERegs = IsRegCall ? 16 : 8; - unsigned NeededInt, NeededSSE; + unsigned NeededInt, NeededSSE, MaxVectorWidth = 0; if (!::classifyReturnType(getCXXABI(), FI, *this)) { if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() && !FI.getReturnType()->getTypePtr()->isUnionType()) { - FI.getReturnInfo() = - classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE); + FI.getReturnInfo() = classifyRegCallStructType( + FI.getReturnType(), NeededInt, NeededSSE, MaxVectorWidth); if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) { FreeIntRegs -= NeededInt; FreeSSERegs -= NeededSSE; @@ -3971,6 +3989,8 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { // integer register. if (FI.getReturnInfo().isIndirect()) --FreeIntRegs; + else if (NeededSSE && MaxVectorWidth > 0) + FI.setMaxVectorWidth(MaxVectorWidth); // The chain argument effectively gives us another free register. if (FI.isChainCall()) @@ -3985,7 +4005,8 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { bool IsNamedArg = ArgNo < NumRequiredArgs; if (IsRegCall && it->type->isStructureOrClassType()) - it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE); + it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE, + MaxVectorWidth); else it->info = classifyArgumentType(it->type, FreeIntRegs, NeededInt, NeededSSE, IsNamedArg); @@ -3997,6 +4018,8 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) { FreeIntRegs -= NeededInt; FreeSSERegs -= NeededSSE; + if (MaxVectorWidth > FI.getMaxVectorWidth()) + FI.setMaxVectorWidth(MaxVectorWidth); } else { it->info = getIndirectResult(it->type, FreeIntRegs); } |