llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Matt Turner (mattst88) <details> <summary>Changes</summary> Two NFC refactors split out of #<!-- -->223481 at review request. - Rename isSingleElementStruct to isSingleElementRecord. It decomposes unions as well as structures, both at the top level and in nested fields and bases; the new name and comment say so, so that a later isSingleElementStruct can refuse unions. - Factor the single-element floating-point/128-bit vector aggregate test that PPC64_SVR4_ABIInfo::computeInfo and getParamTypeAlignment each performed into getSingleElementFPOrVectorType. Assisted-by: Claude Code --- Full diff: https://github.com/llvm/llvm-project/pull/234054.diff 9 Files Affected: - (modified) clang/lib/CodeGen/ABIInfoImpl.cpp (+3-3) - (modified) clang/lib/CodeGen/ABIInfoImpl.h (+6-5) - (modified) clang/lib/CodeGen/Targets/AMDGPU.cpp (+3-3) - (modified) clang/lib/CodeGen/Targets/CSKY.cpp (+1-1) - (modified) clang/lib/CodeGen/Targets/PPC.cpp (+20-18) - (modified) clang/lib/CodeGen/Targets/SPIR.cpp (+3-3) - (modified) clang/lib/CodeGen/Targets/SystemZ.cpp (+4-4) - (modified) clang/lib/CodeGen/Targets/WebAssembly.cpp (+3-3) - (modified) clang/lib/CodeGen/Targets/X86.cpp (+4-4) ``````````diff diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 23b6b7e8200da..a7f88411d0626 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -302,7 +302,7 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, return true; } -const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { +const Type *CodeGen::isSingleElementRecord(QualType T, ASTContext &Context) { const auto *RD = T->getAsRecordDecl(); if (!RD) return nullptr; @@ -325,7 +325,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { // If this is non-empty and not a single element struct, the composite // cannot be a single element struct. - Found = isSingleElementStruct(I.getType(), Context); + Found = isSingleElementRecord(I.getType(), Context); if (!Found) return nullptr; } @@ -354,7 +354,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { if (!isAggregateTypeForABI(FT)) { Found = FT.getTypePtr(); } else { - Found = isSingleElementStruct(FT, Context); + Found = isSingleElementRecord(FT, Context); if (!Found) return nullptr; } diff --git a/clang/lib/CodeGen/ABIInfoImpl.h b/clang/lib/CodeGen/ABIInfoImpl.h index f0276be8cb97f..f9cec462620de 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.h +++ b/clang/lib/CodeGen/ABIInfoImpl.h @@ -120,15 +120,16 @@ bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays, bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr = false); -/// isSingleElementStruct - Determine if a structure is a "single -/// element struct", i.e. it has exactly one non-empty field or +/// isSingleElementRecord - Determine if a record is a "single +/// element record", i.e. it has exactly one non-empty field or /// exactly one field which is itself a single element -/// struct. Structures with flexible array members are never -/// considered single element structs. +/// record. Both structures and unions are decomposed, at the top level +/// and at every level of nesting. Records with flexible array members +/// are never considered single element records. /// /// \return The field declaration for the single non-empty field, if /// it exists. -const Type *isSingleElementStruct(QualType T, ASTContext &Context); +const Type *isSingleElementRecord(QualType T, ASTContext &Context); Address EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, const ABIArgInfo &AI); diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index d54efe81f8cee..fd9182adda47d 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -152,7 +152,7 @@ ABIArgInfo AMDGPUABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); // Lower single-element structs to just return a regular value. - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) + if (const Type *SeltTy = isSingleElementRecord(RetTy, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); if (const auto *RD = RetTy->getAsRecordDecl(); @@ -188,7 +188,7 @@ ABIArgInfo AMDGPUABIInfo::classifyKernelArgumentType(QualType Ty) const { // TODO: Can we omit empty structs? - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + if (const Type *SeltTy = isSingleElementRecord(Ty, getContext())) Ty = QualType(SeltTy, 0); llvm::Type *OrigLTy = CGT.ConvertType(Ty); @@ -243,7 +243,7 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic, // Lower single-element structs to just pass a regular value. TODO: We // could do reasonable-size multiple-element structs too, using getExpand(), // though watch out for things like bitfields. - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + if (const Type *SeltTy = isSingleElementRecord(Ty, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); if (const auto *RD = Ty->getAsRecordDecl(); diff --git a/clang/lib/CodeGen/Targets/CSKY.cpp b/clang/lib/CodeGen/Targets/CSKY.cpp index b9254208f912a..a7455f6b39fb4 100644 --- a/clang/lib/CodeGen/Targets/CSKY.cpp +++ b/clang/lib/CodeGen/Targets/CSKY.cpp @@ -92,7 +92,7 @@ ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, return ABIArgInfo::getIgnore(); if (!Ty->isUnionType()) - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + if (const Type *SeltTy = isSingleElementRecord(Ty, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); uint64_t Size = getContext().getTypeSize(Ty); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index df14719a8c6a8..cac2ee86f7d1f 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -428,7 +428,7 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { // For single-element float/vector structs, we consider the whole type // to have the same alignment requirements as its single element. const Type *AlignTy = nullptr; - if (const Type *EltType = isSingleElementStruct(Ty, getContext())) { + if (const Type *EltType = isSingleElementRecord(Ty, getContext())) { const BuiltinType *BT = EltType->getAs<BuiltinType>(); if ((EltType->isVectorType() && getContext().getTypeSize(EltType) == 128) || (BT && BT->isFloatingPoint())) @@ -667,6 +667,7 @@ class PPC64_SVR4_ABIInfo : public ABIInfo { bool isPromotableTypeForABI(QualType Ty) const; CharUnits getParamTypeAlignment(QualType Ty) const; + const Type *getSingleElementFPOrVectorType(QualType Ty) const; ABIArgInfo classifyReturnType(QualType RetTy) const; ABIArgInfo classifyArgumentType(QualType Ty) const; @@ -688,15 +689,9 @@ class PPC64_SVR4_ABIInfo : public ABIInfo { // We rely on the default argument classification for the most part. // One exception: An aggregate containing a single floating-point // or vector item must be passed in a register if one is available. - const Type *T = isSingleElementStruct(I.type, getContext()); - if (T) { - const BuiltinType *BT = T->getAs<BuiltinType>(); - if ((T->isVectorType() && getContext().getTypeSize(T) == 128) || - (BT && BT->isFloatingPoint())) { - QualType QT(T, 0); - I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT)); - continue; - } + if (const Type *T = getSingleElementFPOrVectorType(I.type)) { + I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QualType(T, 0))); + continue; } I.info = classifyArgumentType(I.type); } @@ -796,14 +791,7 @@ CharUnits PPC64_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { // For single-element float/vector structs, we consider the whole type // to have the same alignment requirements as its single element. - const Type *AlignAsType = nullptr; - const Type *EltType = isSingleElementStruct(Ty, getContext()); - if (EltType) { - const BuiltinType *BT = EltType->getAs<BuiltinType>(); - if ((EltType->isVectorType() && getContext().getTypeSize(EltType) == 128) || - (BT && BT->isFloatingPoint())) - AlignAsType = EltType; - } + const Type *AlignAsType = getSingleElementFPOrVectorType(Ty); // Likewise for ELFv2 homogeneous aggregates. const Type *Base = nullptr; @@ -828,6 +816,20 @@ CharUnits PPC64_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(8); } +/// If Ty is a one-member aggregate wrapping a floating-point or 128-bit vector +/// type, return that type. +const Type * +PPC64_SVR4_ABIInfo::getSingleElementFPOrVectorType(QualType Ty) const { + const Type *EltType = isSingleElementRecord(Ty, getContext()); + if (!EltType) + return nullptr; + const BuiltinType *BT = EltType->getAs<BuiltinType>(); + if ((EltType->isVectorType() && getContext().getTypeSize(EltType) == 128) || + (BT && BT->isFloatingPoint())) + return EltType; + return nullptr; +} + bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { // Homogeneous aggregates for ELFv2 must have base types of float, // double, long double, or 128-bit vectors. diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index 19936d44208dd..8088a09ecdced 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -262,7 +262,7 @@ ABIArgInfo AMDGCNSPIRVABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); // Lower single-element structs to just return a regular value. - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) + if (const Type *SeltTy = isSingleElementRecord(RetTy, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); if (const auto *RD = RetTy->getAsRecordDecl(); @@ -296,7 +296,7 @@ ABIArgInfo AMDGCNSPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const { // TODO: Can we omit empty structs? - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + if (const Type *SeltTy = isSingleElementRecord(Ty, getContext())) Ty = QualType(SeltTy, 0); llvm::Type *OrigLTy = CGT.ConvertType(Ty); @@ -359,7 +359,7 @@ ABIArgInfo AMDGCNSPIRVABIInfo::classifyArgumentType(QualType Ty, // Lower single-element structs to just pass a regular value. TODO: We // could do reasonable-size multiple-element structs too, using getExpand(), // though watch out for things like bitfields. - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + if (const Type *SeltTy = isSingleElementRecord(Ty, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); if (const auto *RD = Ty->getAsRecordDecl(); diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index a27fee633ead2..6c5c2e65dcaf1 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -229,22 +229,22 @@ QualType SystemZABIInfo::getSingleElementType(QualType Ty) const { // Check the fields. for (const auto *FD : RD->fields()) { - // Unlike isSingleElementStruct(), empty structure and array fields + // Unlike isSingleElementRecord(), empty structure and array fields // do count. So do anonymous bitfields that aren't zero-sized. - // Like isSingleElementStruct(), ignore C++20 empty data members. + // Like isSingleElementRecord(), ignore C++20 empty data members. if (FD->hasAttr<NoUniqueAddressAttr>() && isEmptyRecord(getContext(), FD->getType(), true)) continue; - // Unlike isSingleElementStruct(), arrays do not count. + // Unlike isSingleElementRecord(), arrays do not count. // Nested structures still do though. if (!Found.isNull()) return Ty; Found = getSingleElementType(FD->getType()); } - // Unlike isSingleElementStruct(), trailing padding is allowed. + // Unlike isSingleElementRecord(), trailing padding is allowed. // An 8-byte aligned struct s { float f; } is passed as a double. if (!Found.isNull()) return Found; diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp index 8f6f58bfb807e..b892923eddc51 100644 --- a/clang/lib/CodeGen/Targets/WebAssembly.cpp +++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp @@ -150,7 +150,7 @@ ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const { // Lower single-element structs to just pass a regular value. TODO: We // could do reasonable-size multiple-element structs too, using getExpand(), // though watch out for things like bitfields. - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + if (const Type *SeltTy = isSingleElementRecord(Ty, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); // For the experimental multivalue ABI, fully expand all other aggregates if (Kind == WebAssemblyABIKind::ExperimentalMV) { @@ -186,7 +186,7 @@ ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const { // Lower single-element structs to just return a regular value. TODO: We // could do reasonable-size multiple-element structs too, using // ABIArgInfo::getDirect(). - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) + if (const Type *SeltTy = isSingleElementRecord(RetTy, getContext())) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); // For the experimental multivalue ABI, return all other aggregates if (Kind == WebAssemblyABIKind::ExperimentalMV) @@ -202,7 +202,7 @@ RValue WebAssemblyABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const { bool IsIndirect = isAggregateTypeForABI(Ty) && !isEmptyRecord(getContext(), Ty, true) && - !isSingleElementStruct(Ty, getContext()); + !isSingleElementRecord(Ty, getContext()); return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, getContext().getTypeInfoInChars(Ty), CharUnits::fromQuantity(4), diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index c0947c481d2b0..c5c8bd4c0b27d 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -544,7 +544,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, // floating-point register. (MSVC does not apply this special case.) // We apply a similar transformation for pointer types to improve the // quality of the generated IR. - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) + if (const Type *SeltTy = isSingleElementRecord(RetTy, getContext())) if ((!IsWin32StructABI && SeltTy->isRealFloatingType()) || SeltTy->hasPointerRepresentation()) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); @@ -631,7 +631,7 @@ ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal, Realign); } -/// Like isSingleElementStruct, but only looks through one level of records. +/// Like isSingleElementRecord, but only looks through one level of records. /// This mirrors how GCC gives a record the mode of its only field. static const Type *getSingleFieldType(QualType T, ASTContext &Context) { const auto *RD = T->getAsRecordDecl(); @@ -692,7 +692,7 @@ static const Type *getSingleFieldType(QualType T, ASTContext &Context) { X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const { if (getContext().getLangOpts().isCompatibleWith( LangOptions::ClangABI::Ver23)) { - const Type *T = isSingleElementStruct(Ty, getContext()); + const Type *T = isSingleElementRecord(Ty, getContext()); if (!T) T = Ty.getTypePtr(); @@ -2477,7 +2477,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty) const { // Wrapper structs/arrays that only contain vectors are passed just like // vectors; strip them off if present. - if (const Type *InnerTy = isSingleElementStruct(Ty, getContext())) + if (const Type *InnerTy = isSingleElementRecord(Ty, getContext())) Ty = QualType(InnerTy, 0); llvm::Type *IRType = CGT.ConvertType(Ty); `````````` </details> https://github.com/llvm/llvm-project/pull/234054 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
