diff options
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 123 |
1 files changed, 100 insertions, 23 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index e949455..d6efd54 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5452,6 +5452,7 @@ private: ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const; ABIArgInfo classifyArgumentType(QualType RetTy) const; + ABIArgInfo coerceIllegalVector(QualType Ty) const; bool isHomogeneousAggregateBaseType(QualType Ty) const override; bool isHomogeneousAggregateSmallEnough(const Type *Ty, uint64_t Members) const override; @@ -5585,33 +5586,96 @@ void WindowsAArch64TargetCodeGenInfo::setTargetAttributes( } } +ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty) const { + assert(Ty->isVectorType() && "expected vector type!"); + + const auto *VT = Ty->castAs<VectorType>(); + if (VT->getVectorKind() == VectorType::SveFixedLengthPredicateVector) { + assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); + assert(VT->getElementType()->castAs<BuiltinType>()->getKind() == + BuiltinType::UChar && + "unexpected builtin type for SVE predicate!"); + return ABIArgInfo::getDirect(llvm::ScalableVectorType::get( + llvm::Type::getInt1Ty(getVMContext()), 16)); + } + + if (VT->getVectorKind() == VectorType::SveFixedLengthDataVector) { + assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); + + const auto *BT = VT->getElementType()->castAs<BuiltinType>(); + llvm::ScalableVectorType *ResType = nullptr; + switch (BT->getKind()) { + default: + llvm_unreachable("unexpected builtin type for SVE vector!"); + case BuiltinType::SChar: + case BuiltinType::UChar: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getInt8Ty(getVMContext()), 16); + break; + case BuiltinType::Short: + case BuiltinType::UShort: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getInt16Ty(getVMContext()), 8); + break; + case BuiltinType::Int: + case BuiltinType::UInt: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getInt32Ty(getVMContext()), 4); + break; + case BuiltinType::Long: + case BuiltinType::ULong: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getInt64Ty(getVMContext()), 2); + break; + case BuiltinType::Float16: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getHalfTy(getVMContext()), 8); + break; + case BuiltinType::Float: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getFloatTy(getVMContext()), 4); + break; + case BuiltinType::Double: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getDoubleTy(getVMContext()), 2); + break; + case BuiltinType::BFloat16: + ResType = llvm::ScalableVectorType::get( + llvm::Type::getBFloatTy(getVMContext()), 8); + break; + } + return ABIArgInfo::getDirect(ResType); + } + + uint64_t Size = getContext().getTypeSize(Ty); + // Android promotes <2 x i8> to i16, not i32 + if (isAndroid() && (Size <= 16)) { + llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); + return ABIArgInfo::getDirect(ResType); + } + if (Size <= 32) { + llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext()); + return ABIArgInfo::getDirect(ResType); + } + if (Size == 64) { + auto *ResType = + llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2); + return ABIArgInfo::getDirect(ResType); + } + if (Size == 128) { + auto *ResType = + llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4); + return ABIArgInfo::getDirect(ResType); + } + return getNaturalAlignIndirect(Ty, /*ByVal=*/false); +} + ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const { Ty = useFirstFieldIfTransparentUnion(Ty); // Handle illegal vector types here. - if (isIllegalVectorType(Ty)) { - uint64_t Size = getContext().getTypeSize(Ty); - // Android promotes <2 x i8> to i16, not i32 - if (isAndroid() && (Size <= 16)) { - llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - if (Size <= 32) { - llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - if (Size == 64) { - auto *ResType = - llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2); - return ABIArgInfo::getDirect(ResType); - } - if (Size == 128) { - auto *ResType = - llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4); - return ABIArgInfo::getDirect(ResType); - } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - } + if (isIllegalVectorType(Ty)) + return coerceIllegalVector(Ty); if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. @@ -5690,6 +5754,12 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); + if (const auto *VT = RetTy->getAs<VectorType>()) { + if (VT->getVectorKind() == VectorType::SveFixedLengthDataVector || + VT->getVectorKind() == VectorType::SveFixedLengthPredicateVector) + return coerceIllegalVector(RetTy); + } + // Large vector types should be returned via memory. if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) return getNaturalAlignIndirect(RetTy); @@ -5745,6 +5815,13 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, /// isIllegalVectorType - check whether the vector type is legal for AArch64. bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const { if (const VectorType *VT = Ty->getAs<VectorType>()) { + // Check whether VT is a fixed-length SVE vector. These types are + // represented as scalable vectors in function args/return and must be + // coerced from fixed vectors. + if (VT->getVectorKind() == VectorType::SveFixedLengthDataVector || + VT->getVectorKind() == VectorType::SveFixedLengthPredicateVector) + return true; + // Check whether VT is legal. unsigned NumElements = VT->getNumElements(); uint64_t Size = getContext().getTypeSize(VT); |