[clang] [llvm] [LLVMABI][AARCH64] Handle vector types (PR #225201)
Madhur Amilkanthwar via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 01:47:20 PDT 2026
================
@@ -195,10 +230,114 @@ ArgInfo AArch64TargetInfo::classifyArgumentType(
}
bool AArch64TargetInfo::passAsAggregateType(const Type *Ty) const {
- // TODO: Handle SVE types. For now, they don't get through the type mapper.
+ if (Opts.Kind == AArch64ABIKind::AAPCS && Ty->isSVESizelessType()) {
+ // svcount_t and the single-vector types occupy a register of their own,
+ // so only the data and predicate tuples are passed as aggregates.
+ const auto *TupleTy = dyn_cast<TupleType>(Ty);
+ assert((!TupleTy || TupleTy->getNumVectors() > 1) &&
+ "unexpected single vector tuple");
+ return TupleTy && !TupleTy->getVectorType()->isSVECount();
+ }
return isAggregateTypeForABI(Ty);
}
+/// Returns the scalable vector type that \p VT, a fixed-length SVE vector,
+/// is passed as. A scalable SVE vector holds 128 bits per granule, so the
+/// scalable element count is 128 divided by the element size, regardless of
+/// how many elements the fixed-length type has.
+const VectorType *AArch64TargetInfo::convertFixedToScalableVectorType(
+ const VectorType *VT) const {
+ // TODO: Verify that this correctly handles MFloat8 when we decide on a
+ // mapping for that type.
+
+ if (VT->isFixedLengthSVEPredicate())
+ return TB.getScalablePredicateVectorType();
+
+ assert(VT->isFixedLengthSVEData() && "expected a fixed-length SVE vector!");
+
+ const Type *EltTy = VT->getElementType();
+ uint64_t EltBits = EltTy->getSizeInBits().getFixedValue();
+ assert(EltBits >= 8 && EltBits <= 64 && isPowerOf2_64(EltBits) &&
+ "unexpected element type for SVE data vector!");
+
+ return TB.getVectorType(EltTy, ElementCount::getScalable(128 / EltBits),
+ llvm::Align(16), VectorKind::SVEData);
+}
+
+ArgInfo AArch64TargetInfo::coerceIllegalVector(const Type *Ty, unsigned &NSRN,
+ unsigned &NPRN) const {
+ const auto *VT = cast<VectorType>(Ty);
+
+ if (VT->isFixedLengthSVEPredicate()) {
+ // Fixed-length predicates are described with 8-bit elements, but they are
+ // passed in a predicate register as a scalable vector of 16 one-bit
+ // elements.
+ assert(isa<IntegerType>(VT->getElementType()) &&
+ VT->getElementType()->getSizeInBits().getFixedValue() == 8 &&
+ "unexpected element type for SVE predicate!");
+ NPRN = std::min(NPRN + 1, 4u);
+ return ArgInfo::getDirect(TB.getScalablePredicateVectorType());
+ }
+
+ if (VT->isFixedLengthSVEData()) {
+ NSRN = std::min(NSRN + 1, 8u);
+ return ArgInfo::getDirect(convertFixedToScalableVectorType(VT));
+ }
+
+ uint64_t Size = VT->getABISizeInBits();
+ // Android promotes <2 x i8> to i16, not i32
+ if (Opts.IsAndroidOrOHOS && (Size <= 16)) {
+ auto *ResType = TB.getIntegerType(16, llvm::Align(2), /*Signed=*/false);
+ return ArgInfo::getDirect(ResType);
+ }
+ const Type *I32 = TB.getIntegerType(32, llvm::Align(4), /*Signed=*/false);
+ if (Size <= 32)
+ return ArgInfo::getDirect(I32);
+ if (Size == 64) {
+ NSRN = std::min(NSRN + 1, 8u);
+ return ArgInfo::getDirect(
+ TB.getVectorType(I32, ElementCount::getFixed(2), llvm::Align(8)));
+ }
+ if (Size == 128) {
+ NSRN = std::min(NSRN + 1, 8u);
+ return ArgInfo::getDirect(
+ TB.getVectorType(I32, ElementCount::getFixed(4), llvm::Align(16)));
+ }
+
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+}
+
+bool AArch64TargetInfo::isIllegalVectorType(const Type *Ty) const {
+ if (const auto *VT = dyn_cast<VectorType>(Ty)) {
+ // 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->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate())
+ return true;
+
+ // Scalable SVE types are legal.
+ if (VT->isScalable())
+ return false;
+
+ // Check whether VT is legal.
+ assert(VT->getNumElements().isFixed() &&
+ "expected fixed number of elements!");
+ unsigned NumElements = VT->getNumElements().getKnownMinValue();
+ uint64_t Size = VT->getABISizeInBits();
+ // NumElements should be power of 2.
+ if (!llvm::isPowerOf2_32(NumElements))
----------------
madhur13490 wrote:
Nit: llvm:: isn't needed here since we're inside namespace llvm, and line 260 calls isPowerOf2_64 without it.
https://github.com/llvm/llvm-project/pull/225201
More information about the llvm-commits
mailing list