diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index a3e3a38a1033b..29998f361926a 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -7486,13 +7486,10 @@ void TCETargetCodeGenInfo::setTargetAttributes( namespace { class HexagonABIInfo : public ABIInfo { - - public: HexagonABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} private: - ABIArgInfo classifyReturnType(QualType RetTy) const; ABIArgInfo classifyArgumentType(QualType RetTy) const; @@ -7505,14 +7502,14 @@ class HexagonABIInfo : public ABIInfo { class HexagonTargetCodeGenInfo : public TargetCodeGenInfo { public: HexagonTargetCodeGenInfo(CodeGenTypes &CGT) - :TargetCodeGenInfo(new HexagonABIInfo(CGT)) {} + : TargetCodeGenInfo(new HexagonABIInfo(CGT)) {} int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { return 29; } }; -} +} // namespace void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const { if (!getCXXABI().classifyReturnType(FI)) @@ -7527,8 +7524,8 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const { if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + return Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect(); } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) @@ -7539,53 +7536,56 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const { return ABIArgInfo::getIgnore(); uint64_t Size = getContext().getTypeSize(Ty); - if (Size > 64) - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + if (Size <= 64) { // Pass in the smallest viable integer type. - else if (Size > 32) - return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext())); - else if (Size > 16) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - else if (Size > 8) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - else - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); + if (!llvm::isPowerOf2_64(Size)) + Size = llvm::NextPowerOf2(Size); + return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size)); + } + return getNaturalAlignIndirect(Ty, /*ByVal=*/true); } ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); - // Large vector types should be returned via memory. - if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 64) - return getNaturalAlignIndirect(RetTy); + const TargetInfo &T = CGT.getTarget(); + uint64_t Size = getContext().getTypeSize(RetTy); + + if (const auto *VecTy = RetTy->getAs()) { + // HVX vectors are returned in vector registers or register pairs. + if (T.hasFeature("hvx")) { + assert(T.hasFeature("hvx-length64b") || T.hasFeature("hvx-length128b")); + uint64_t VecSize = T.hasFeature("hvx-length64b") ? 64*8 : 128*8; + if (Size == VecSize || Size == 2*VecSize) + return ABIArgInfo::getDirectInReg(); + } + + // Large vector types should be returned via memory. + if (Size > 64) + return getNaturalAlignIndirect(RetTy); + } if (!isAggregateTypeForABI(RetTy)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); + return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect(); } if (isEmptyRecord(getContext(), RetTy, true)) return ABIArgInfo::getIgnore(); - // Aggregates <= 8 bytes are returned in r0; other aggregates + // Aggregates <= 8 bytes are returned in registers, other aggregates // are returned indirectly. - uint64_t Size = getContext().getTypeSize(RetTy); if (Size <= 64) { // Return in the smallest viable integer type. - if (Size <= 8) - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - if (Size <= 32) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext())); + if (!llvm::isPowerOf2_64(Size)) + Size = llvm::NextPowerOf2(Size); + return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size)); } - return getNaturalAlignIndirect(RetTy, /*ByVal=*/true); } diff --git a/clang/test/CodeGen/hexagon-hvx-abi.c b/clang/test/CodeGen/hexagon-hvx-abi.c new file mode 100644 index 0000000000000..cd70f57e4ffca --- /dev/null +++ b/clang/test/CodeGen/hexagon-hvx-abi.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple hexagon -emit-llvm -target-cpu hexagonv66 -target-feature +hvxv66 -target-feature +hvx-length64b -o - %s | FileCheck %s --check-prefix CHECK-HVX64 +// RUN: %clang_cc1 -triple hexagon -emit-llvm -target-cpu hexagonv66 -target-feature +hvxv66 -target-feature +hvx-length128b -o - %s | FileCheck %s --check-prefix CHECK-HVX128 + +typedef long HVX_Vector __attribute__((__vector_size__(__HVX_LENGTH__))) + __attribute__((aligned(__HVX_LENGTH__))); +typedef long HVX_VectorPair __attribute__((__vector_size__(2*__HVX_LENGTH__))) + __attribute__((aligned(__HVX_LENGTH__))); + +// CHECK-HVX64: define {{.*}} <16 x i32> @foo(<16 x i32> %a, <32 x i32> %b) +// CHECK-HVX128: define {{.*}} <32 x i32> @foo(<32 x i32> %a, <64 x i32> %b) +HVX_Vector foo(HVX_Vector a, HVX_VectorPair b) { + return a; +} + +// CHECK-HVX64: define {{.*}} <32 x i32> @bar(<16 x i32> %a, <32 x i32> %b) +// CHECK-HVX128: define {{.*}} <64 x i32> @bar(<32 x i32> %a, <64 x i32> %b) +HVX_VectorPair bar(HVX_Vector a, HVX_VectorPair b) { + return b; +} +