From: Oliver Stannard Date: Wed, 27 Aug 2014 10:43:15 +0000 (+0000) Subject: Move some ARM-specific code from CGCall.cpp to TargetInfo.cpp X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2269a203b798ea17f7466b7341623af3cbebd0e6;p=clang Move some ARM-specific code from CGCall.cpp to TargetInfo.cpp This tidies up some ARM-specific code added by r208417 to move it out of the target-independent parts of clang into TargetInfo.cpp. This also has the advantage that we can now flatten struct arguments to variadic AAPCS functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216535 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h index 38dc93278e..bc4d25cb88 100644 --- a/include/clang/CodeGen/CGFunctionInfo.h +++ b/include/clang/CodeGen/CGFunctionInfo.h @@ -87,6 +87,7 @@ private: bool IndirectRealign : 1; // isIndirect() bool SRetAfterThis : 1; // isIndirect() bool InReg : 1; // isDirect() || isExtend() || isIndirect() + bool CanBeFlattened: 1; // isDirect() ABIArgInfo(Kind K) : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {} @@ -97,11 +98,13 @@ public: TheKind(Direct), PaddingInReg(false), InReg(false) {} static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, - llvm::Type *Padding = nullptr) { + llvm::Type *Padding = nullptr, + bool CanBeFlattened = true) { auto AI = ABIArgInfo(Direct); AI.setCoerceToType(T); AI.setDirectOffset(Offset); AI.setPaddingType(Padding); + AI.setCanBeFlattened(CanBeFlattened); return AI; } static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { @@ -265,6 +268,16 @@ public: InAllocaSRet = SRet; } + bool getCanBeFlattened() const { + assert(isDirect() && "Invalid kind!"); + return CanBeFlattened; + } + + void setCanBeFlattened(bool Flatten) { + assert(isDirect() && "Invalid kind!"); + CanBeFlattened = Flatten; + } + void dump() const; }; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 38a9df37f2..45a6259089 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -139,23 +139,6 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { return CC_C; } -static bool isAAPCSVFP(const CGFunctionInfo &FI, const TargetInfo &Target) { - switch (FI.getEffectiveCallingConvention()) { - case llvm::CallingConv::C: - switch (Target.getTriple().getEnvironment()) { - case llvm::Triple::EABIHF: - case llvm::Triple::GNUEABIHF: - return true; - default: - return false; - } - case llvm::CallingConv::ARM_AAPCS_VFP: - return true; - default: - return false; - } -} - /// Arrange the argument and result information for a call to an /// unknown C++ non-static member function of the given abstract type. /// (Zero value of RD means we don't have any meaningful "this" argument type, @@ -989,14 +972,11 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { case ABIArgInfo::Extend: case ABIArgInfo::Direct: { - // If the coerce-to type is a first class aggregate, flatten it. Either - // way is semantically identical, but fast-isel and the optimizer - // generally likes scalar values better than FCAs. - // We cannot do this for functions using the AAPCS calling convention, - // as structures are treated differently by that calling convention. + // Fast-isel and the optimizer generally like scalar values better than + // FCAs, so we flatten them if this is safe to do for this argument. llvm::Type *argType = argAI.getCoerceToType(); llvm::StructType *st = dyn_cast(argType); - if (st && !isAAPCSVFP(FI, getTarget())) { + if (st && argAI.isDirect() && argAI.getCanBeFlattened()) { for (unsigned i = 0, e = st->getNumElements(); i != e; ++i) argTypes.push_back(st->getElementType(i)); } else { @@ -1134,7 +1114,7 @@ void ClangToLLVMArgMapping::construct(CodeGenModule &CGM, case ABIArgInfo::Direct: { // FIXME: handle sseregparm someday... llvm::StructType *STy = dyn_cast(AI.getCoerceToType()); - if (!isAAPCSVFP(FI, CGM.getTarget()) && STy) { + if (AI.isDirect() && AI.getCanBeFlattened() && STy) { IRArgs.NumberOfArgs = STy->getNumElements(); } else { IRArgs.NumberOfArgs = 1; @@ -1671,13 +1651,11 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::PointerType::getUnqual(ArgI.getCoerceToType())); } - // If the coerce-to type is a first class aggregate, we flatten it and - // pass the elements. Either way is semantically identical, but fast-isel - // and the optimizer generally likes scalar values better than FCAs. - // We cannot do this for functions using the AAPCS calling convention, - // as structures are treated differently by that calling convention. + // Fast-isel and the optimizer generally like scalar values better than + // FCAs, so we flatten them if this is safe to do for this argument. llvm::StructType *STy = dyn_cast(ArgI.getCoerceToType()); - if (!isAAPCSVFP(FI, getTarget()) && STy && STy->getNumElements() > 1) { + if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy && + STy->getNumElements() > 1) { uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(STy); llvm::Type *DstTy = cast(Ptr->getType())->getElementType(); @@ -2928,14 +2906,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } - // If the coerce-to type is a first class aggregate, we flatten it and - // pass the elements. Either way is semantically identical, but fast-isel - // and the optimizer generally likes scalar values better than FCAs. - // We cannot do this for functions using the AAPCS calling convention, - // as structures are treated differently by that calling convention. + // Fast-isel and the optimizer generally like scalar values better than + // FCAs, so we flatten them if this is safe to do for this argument. llvm::StructType *STy = dyn_cast(ArgInfo.getCoerceToType()); - if (STy && !isAAPCSVFP(CallInfo, getTarget())) { + if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) { llvm::Type *SrcTy = cast(SrcPtr->getType())->getElementType(); uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy); diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 8340261ad8..c27e2cf42f 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -4169,6 +4169,9 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { // unallocated are marked as unavailable. resetAllocatedRegs(); + const bool isAAPCS_VFP = + getABIKind() == ARMABIInfo::AAPCS_VFP && !FI.isVariadic(); + if (getCXXABI().classifyReturnType(FI)) { if (FI.getReturnInfo().isIndirect()) markAllocatedGPRs(1, 1); @@ -4199,10 +4202,10 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs); if (I.info.canHaveCoerceToType()) { I.info = ABIArgInfo::getDirect(I.info.getCoerceToType() /* type */, 0 /* offset */, - PaddingTy); + PaddingTy, !isAAPCS_VFP); } else { I.info = ABIArgInfo::getDirect(nullptr /* type */, 0 /* offset */, - PaddingTy); + PaddingTy, !isAAPCS_VFP); } } } @@ -4398,6 +4401,9 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, // 64-bit containerized vectors or 128-bit containerized vectors with one // to four Elements. + const bool isAAPCS_VFP = + getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic; + // Handle illegal vector types here. if (isIllegalVectorType(Ty)) { uint64_t Size = getContext().getTypeSize(Ty); @@ -4405,7 +4411,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext()); markAllocatedGPRs(1, 1); - return ABIArgInfo::getDirect(ResType); + return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP); } if (Size == 64) { llvm::Type *ResType = llvm::VectorType::get( @@ -4416,7 +4422,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, markAllocatedVFPs(2, 2); IsCPRC = true; } - return ABIArgInfo::getDirect(ResType); + return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP); } if (Size == 128) { llvm::Type *ResType = llvm::VectorType::get( @@ -4427,7 +4433,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, markAllocatedVFPs(4, 4); IsCPRC = true; } - return ABIArgInfo::getDirect(ResType); + return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP); } markAllocatedGPRs(1, 1); return ABIArgInfo::getIndirect(0, /*ByVal=*/false); @@ -4466,8 +4472,9 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, unsigned Size = getContext().getTypeSize(Ty); if (!IsCPRC) markAllocatedGPRs(Size > 32 ? 2 : 1, (Size + 31) / 32); - return (Ty->isPromotableIntegerType() ? - ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + return (Ty->isPromotableIntegerType() + ? ABIArgInfo::getExtend() + : ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP)); } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { @@ -4479,7 +4486,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, if (isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); - if (getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic) { + if (isAAPCS_VFP) { // Homogeneous Aggregates need to be expanded when we can fit the aggregate // into VFP registers. const Type *Base = nullptr; @@ -4500,7 +4507,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, markAllocatedVFPs(2, Members * 2); } IsCPRC = true; - return ABIArgInfo::getDirect(); + return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP); } } @@ -4540,7 +4547,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, llvm::Type *STy = llvm::StructType::get(llvm::ArrayType::get(ElemTy, SizeRegs), NULL); - return ABIArgInfo::getDirect(STy); + return ABIArgInfo::getDirect(STy, 0, nullptr, !isAAPCS_VFP); } static bool isIntegerLikeType(QualType Ty, ASTContext &Context, @@ -4630,6 +4637,9 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context, ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic) const { + const bool isAAPCS_VFP = + getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic; + if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); @@ -4644,8 +4654,9 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() ? - ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + return (RetTy->isPromotableIntegerType() + ? ABIArgInfo::getExtend() + : ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP)); } // Are we following APCS? @@ -4658,8 +4669,8 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, // FIXME: Consider using 2 x vector types if the back end handles them // correctly. if (RetTy->isAnyComplexType()) - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), - getContext().getTypeSize(RetTy))); + return ABIArgInfo::getDirect(llvm::IntegerType::get( + getVMContext(), getContext().getTypeSize(RetTy))); // Integer like structures are returned in r0. if (isIntegerLikeType(RetTy, getContext(), getVMContext())) { @@ -4688,7 +4699,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, if (isHomogeneousAggregate(RetTy, Base, getContext())) { assert(Base && "Base class should be set for homogeneous aggregate"); // Homogeneous Aggregates are returned directly. - return ABIArgInfo::getDirect(); + return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP); } } @@ -4698,14 +4709,18 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, if (Size <= 32) { if (getDataLayout().isBigEndian()) // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); + return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()), 0, + nullptr, !isAAPCS_VFP); // Return in the smallest viable integer type. if (Size <= 8) - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); + return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()), 0, + nullptr, !isAAPCS_VFP); if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); + return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()), 0, + nullptr, !isAAPCS_VFP); + return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()), 0, + nullptr, !isAAPCS_VFP); } markAllocatedGPRs(1, 1); diff --git a/test/CodeGen/arm-homogenous.c b/test/CodeGen/arm-homogenous.c index d1b489793f..897f9e6fe8 100644 --- a/test/CodeGen/arm-homogenous.c +++ b/test/CodeGen/arm-homogenous.c @@ -186,7 +186,7 @@ extern void takes_struct_of_four_doubles_variadic(double a, struct_of_four_doubl void test_struct_of_four_doubles_variadic(void) { // CHECK: test_struct_of_four_doubles_variadic -// CHECK: call arm_aapcs_vfpcc void (double, { [4 x i64] }, { [4 x i64] }, double, ...)* @takes_struct_of_four_doubles_variadic(double {{.*}}, { [4 x i64] } {{.*}}, { [4 x i64] } {{.*}}, double {{.*}}) +// CHECK: call arm_aapcs_vfpcc void (double, [4 x i64], [4 x i64], double, ...)* @takes_struct_of_four_doubles_variadic(double {{.*}}, [4 x i64] {{.*}}, [4 x i64] {{.*}}, double {{.*}}) takes_struct_of_four_doubles_variadic(3.0, g_s4d, g_s4d, 4.0); }