#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
-#include "llvm/Support/ScalableSize.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Alignment.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <cstdint>
#include <string>
/// Returns the number of bits necessary to hold the specified type.
///
+ /// If Ty is a scalable vector type, the scalable property will be set and
+ /// the runtime size will be a positive integer multiple of the base size.
+ ///
/// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must
/// have a size (Type::isSized() must return true).
- uint64_t getTypeSizeInBits(Type *Ty) const;
+ TypeSize getTypeSizeInBits(Type *Ty) const;
/// Returns the maximum number of bytes that may be overwritten by
/// storing the specified type.
///
+ /// If Ty is a scalable vector type, the scalable property will be set and
+ /// the runtime size will be a positive integer multiple of the base size.
+ ///
/// For example, returns 5 for i36 and 10 for x86_fp80.
- uint64_t getTypeStoreSize(Type *Ty) const {
- return (getTypeSizeInBits(Ty) + 7) / 8;
+ TypeSize getTypeStoreSize(Type *Ty) const {
+ auto BaseSize = getTypeSizeInBits(Ty);
+ return { (BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable() };
}
/// Returns the maximum number of bits that may be overwritten by
/// storing the specified type; always a multiple of 8.
///
+ /// If Ty is a scalable vector type, the scalable property will be set and
+ /// the runtime size will be a positive integer multiple of the base size.
+ ///
/// For example, returns 40 for i36 and 80 for x86_fp80.
- uint64_t getTypeStoreSizeInBits(Type *Ty) const {
+ TypeSize getTypeStoreSizeInBits(Type *Ty) const {
return 8 * getTypeStoreSize(Ty);
}
/// Returns the offset in bytes between successive objects of the
/// specified type, including alignment padding.
///
+ /// If Ty is a scalable vector type, the scalable property will be set and
+ /// the runtime size will be a positive integer multiple of the base size.
+ ///
/// This is the amount that alloca reserves for this type. For example,
/// returns 12 or 16 for x86_fp80, depending on alignment.
- uint64_t getTypeAllocSize(Type *Ty) const {
+ TypeSize getTypeAllocSize(Type *Ty) const {
// Round up to the next alignment boundary.
return alignTo(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
}
/// Returns the offset in bits between successive objects of the
/// specified type, including alignment padding; always a multiple of 8.
///
+ /// If Ty is a scalable vector type, the scalable property will be set and
+ /// the runtime size will be a positive integer multiple of the base size.
+ ///
/// This is the amount that alloca reserves for this type. For example,
/// returns 96 or 128 for x86_fp80, depending on alignment.
- uint64_t getTypeAllocSizeInBits(Type *Ty) const {
+ TypeSize getTypeAllocSizeInBits(Type *Ty) const {
return 8 * getTypeAllocSize(Ty);
}
// The implementation of this method is provided inline as it is particularly
// well suited to constant folding when called on a specific Type subclass.
-inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
+inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
switch (Ty->getTypeID()) {
case Type::LabelTyID:
- return getPointerSizeInBits(0);
+ return TypeSize::Fixed(getPointerSizeInBits(0));
case Type::PointerTyID:
- return getPointerSizeInBits(Ty->getPointerAddressSpace());
+ return TypeSize::Fixed(getPointerSizeInBits(Ty->getPointerAddressSpace()));
case Type::ArrayTyID: {
ArrayType *ATy = cast<ArrayType>(Ty);
return ATy->getNumElements() *
}
case Type::StructTyID:
// Get the layout annotation... which is lazily created on demand.
- return getStructLayout(cast<StructType>(Ty))->getSizeInBits();
+ return TypeSize::Fixed(
+ getStructLayout(cast<StructType>(Ty))->getSizeInBits());
case Type::IntegerTyID:
- return Ty->getIntegerBitWidth();
+ return TypeSize::Fixed(Ty->getIntegerBitWidth());
case Type::HalfTyID:
- return 16;
+ return TypeSize::Fixed(16);
case Type::FloatTyID:
- return 32;
+ return TypeSize::Fixed(32);
case Type::DoubleTyID:
case Type::X86_MMXTyID:
- return 64;
+ return TypeSize::Fixed(64);
case Type::PPC_FP128TyID:
case Type::FP128TyID:
- return 128;
+ return TypeSize::Fixed(128);
// In memory objects this is always aligned to a higher boundary, but
// only 80 bits contain information.
case Type::X86_FP80TyID:
- return 80;
+ return TypeSize::Fixed(80);
case Type::VectorTyID: {
VectorType *VTy = cast<VectorType>(Ty);
- return VTy->getNumElements() * getTypeSizeInBits(VTy->getElementType());
+ auto EltCnt = VTy->getElementCount();
+ uint64_t MinBits = EltCnt.Min *
+ getTypeSizeInBits(VTy->getElementType()).getFixedSize();
+ return TypeSize(MinBits, EltCnt.Scalable);
}
default:
llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type");
#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ScalableSize.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <cstdint>
static Type* makeCmpResultType(Type* opnd_type) {
if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) {
return VectorType::get(Type::getInt1Ty(opnd_type->getContext()),
- vt->getNumElements());
+ vt->getElementCount());
}
return Type::getInt1Ty(opnd_type->getContext());
}
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <cstdint>
#include <iterator>
/// This will return zero if the type does not have a size or is not a
/// primitive type.
///
+ /// If this is a scalable vector type, the scalable property will be set and
+ /// the runtime size will be a positive integer multiple of the base size.
+ ///
/// Note that this may not reflect the size of memory allocated for an
/// instance of the type or the number of bytes that are written when an
/// instance of the type is stored to memory. The DataLayout class provides
/// additional query functions to provide this information.
///
- unsigned getPrimitiveSizeInBits() const LLVM_READONLY;
+ TypeSize getPrimitiveSizeInBits() const LLVM_READONLY;
/// If this is a vector type, return the getPrimitiveSizeInBits value for the
/// element type. Otherwise return the getPrimitiveSizeInBits value for this
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/ScalableSize.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
namespace llvm {
+++ /dev/null
-//===- ScalableSize.h - Scalable vector size info ---------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides a struct that can be used to query the size of IR types
-// which may be scalable vectors. It provides convenience operators so that
-// it can be used in much the same way as a single scalar value.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_SCALABLESIZE_H
-#define LLVM_SUPPORT_SCALABLESIZE_H
-
-namespace llvm {
-
-class ElementCount {
-public:
- unsigned Min; // Minimum number of vector elements.
- bool Scalable; // If true, NumElements is a multiple of 'Min' determined
- // at runtime rather than compile time.
-
- ElementCount(unsigned Min, bool Scalable)
- : Min(Min), Scalable(Scalable) {}
-
- ElementCount operator*(unsigned RHS) {
- return { Min * RHS, Scalable };
- }
- ElementCount operator/(unsigned RHS) {
- return { Min / RHS, Scalable };
- }
-
- bool operator==(const ElementCount& RHS) const {
- return Min == RHS.Min && Scalable == RHS.Scalable;
- }
- bool operator!=(const ElementCount& RHS) const {
- return !(*this == RHS);
- }
-};
-
-} // end namespace llvm
-
-#endif // LLVM_SUPPORT_SCALABLESIZE_H
--- /dev/null
+//===- TypeSize.h - Wrapper around type sizes -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a struct that can be used to query the size of IR types
+// which may be scalable vectors. It provides convenience operators so that
+// it can be used in much the same way as a single scalar value.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPESIZE_H
+#define LLVM_SUPPORT_TYPESIZE_H
+
+#include <tuple>
+
+namespace llvm {
+
+class ElementCount {
+public:
+ unsigned Min; // Minimum number of vector elements.
+ bool Scalable; // If true, NumElements is a multiple of 'Min' determined
+ // at runtime rather than compile time.
+
+ ElementCount(unsigned Min, bool Scalable)
+ : Min(Min), Scalable(Scalable) {}
+
+ ElementCount operator*(unsigned RHS) {
+ return { Min * RHS, Scalable };
+ }
+ ElementCount operator/(unsigned RHS) {
+ return { Min / RHS, Scalable };
+ }
+
+ bool operator==(const ElementCount& RHS) const {
+ return Min == RHS.Min && Scalable == RHS.Scalable;
+ }
+ bool operator!=(const ElementCount& RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+// This class is used to represent the size of types. If the type is of fixed
+// size, it will represent the exact size. If the type is a scalable vector,
+// it will represent the known minimum size.
+class TypeSize {
+ uint64_t MinSize; // The known minimum size.
+ bool IsScalable; // If true, then the runtime size is an integer multiple
+ // of MinSize.
+
+public:
+ constexpr TypeSize(uint64_t MinSize, bool Scalable)
+ : MinSize(MinSize), IsScalable(Scalable) {}
+
+ static constexpr TypeSize Fixed(uint64_t Size) {
+ return TypeSize(Size, /*IsScalable=*/false);
+ }
+
+ static constexpr TypeSize Scalable(uint64_t MinSize) {
+ return TypeSize(MinSize, /*IsScalable=*/true);
+ }
+
+ // Scalable vector types with the same minimum size as a fixed size type are
+ // not guaranteed to be the same size at runtime, so they are never
+ // considered to be equal.
+ friend bool operator==(const TypeSize &LHS, const TypeSize &RHS) {
+ return std::tie(LHS.MinSize, LHS.IsScalable) ==
+ std::tie(RHS.MinSize, RHS.IsScalable);
+ }
+
+ friend bool operator!=(const TypeSize &LHS, const TypeSize &RHS) {
+ return !(LHS == RHS);
+ }
+
+ // For many cases, size ordering between scalable and fixed size types cannot
+ // be determined at compile time, so such comparisons aren't allowed.
+ //
+ // e.g. <vscale x 2 x i16> could be bigger than <4 x i32> with a runtime
+ // vscale >= 5, equal sized with a vscale of 4, and smaller with
+ // a vscale <= 3.
+ //
+ // If the scalable flags match, just perform the requested comparison
+ // between the minimum sizes.
+ friend bool operator<(const TypeSize &LHS, const TypeSize &RHS) {
+ assert(LHS.IsScalable == RHS.IsScalable &&
+ "Ordering comparison of scalable and fixed types");
+
+ return LHS.MinSize < RHS.MinSize;
+ }
+
+ friend bool operator>(const TypeSize &LHS, const TypeSize &RHS) {
+ return RHS < LHS;
+ }
+
+ friend bool operator<=(const TypeSize &LHS, const TypeSize &RHS) {
+ return !(RHS < LHS);
+ }
+
+ friend bool operator>=(const TypeSize &LHS, const TypeSize& RHS) {
+ return !(LHS < RHS);
+ }
+
+ // Convenience operators to obtain relative sizes independently of
+ // the scalable flag.
+ TypeSize operator*(unsigned RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ friend TypeSize operator*(const unsigned LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ TypeSize operator/(unsigned RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ // Return the minimum size with the assumption that the size is exact.
+ // Use in places where a scalable size doesn't make sense (e.g. non-vector
+ // types, or vectors in backends which don't support scalable vectors)
+ uint64_t getFixedSize() const {
+ assert(!IsScalable && "Request for a fixed size on a scalable object");
+ return MinSize;
+ }
+
+ // Return the known minimum size. Use in places where the scalable property
+ // doesn't matter (e.g. determining alignment) or in conjunction with the
+ // isScalable method below.
+ uint64_t getKnownMinSize() const {
+ return MinSize;
+ }
+
+ // Return whether or not the size is scalable.
+ bool isScalable() const {
+ return IsScalable;
+ }
+
+ // Casts to a uint64_t if this is a fixed-width size.
+ //
+ // NOTE: This interface is obsolete and will be removed in a future version
+ // of LLVM in favour of calling getFixedSize() directly
+ operator uint64_t() const {
+ return getFixedSize();
+ }
+
+ // Additional convenience operators needed to avoid ambiguous parses
+ // TODO: Make uint64_t the default operator?
+ TypeSize operator*(uint64_t RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ TypeSize operator*(int RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ TypeSize operator*(int64_t RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ friend TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ friend TypeSize operator*(const int LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ friend TypeSize operator*(const int64_t LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ TypeSize operator/(uint64_t RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ TypeSize operator/(int RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ TypeSize operator/(int64_t RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+};
+
+/// Returns a TypeSize with a known minimum size that is the next integer
+/// (mod 2**64) that is greater than or equal to \p Value and is a multiple
+/// of \p Align. \p Align must be non-zero.
+///
+/// Similar to the alignTo functions in MathExtras.h
+inline TypeSize alignTo(TypeSize Size, uint64_t Align) {
+ assert(Align != 0u && "Align must be non-zero");
+ return {(Size.getKnownMinSize() + Align - 1) / Align * Align,
+ Size.isScalable()};
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TypeSize_H
if (auto *AllocSize = dyn_cast_or_null<ConstantInt>(Size)) {
Type *Ty = I.getAllocatedType();
AllocatedSize = SaturatingMultiplyAdd(
- AllocSize->getLimitedValue(), DL.getTypeAllocSize(Ty), AllocatedSize);
+ AllocSize->getLimitedValue(), DL.getTypeAllocSize(Ty).getFixedSize(),
+ AllocatedSize);
return Base::visitAlloca(I);
}
}
// Accumulate the allocated size.
if (I.isStaticAlloca()) {
Type *Ty = I.getAllocatedType();
- AllocatedSize = SaturatingAdd(DL.getTypeAllocSize(Ty), AllocatedSize);
+ AllocatedSize = SaturatingAdd(DL.getTypeAllocSize(Ty).getFixedSize(),
+ AllocatedSize);
}
// We will happily inline static alloca instructions.
NoopInput = Op;
} else if (isa<TruncInst>(I) &&
TLI.allowTruncateForTailCall(Op->getType(), I->getType())) {
- DataBits = std::min(DataBits, I->getType()->getPrimitiveSizeInBits());
+ DataBits = std::min((uint64_t)DataBits,
+ I->getType()->getPrimitiveSizeInBits().getFixedSize());
NoopInput = Op;
} else if (auto CS = ImmutableCallSite(I)) {
const Value *ReturnedOp = CS.getReturnedArgOperand();
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TypeSize.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
llvm_unreachable("Bad type for getAlignment!!!");
}
- return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty), abi_or_pref, Ty);
+ // If we're dealing with a scalable vector, we just need the known minimum
+ // size for determining alignment. If not, we'll get the exact size.
+ return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty).getKnownMinSize(),
+ abi_or_pref, Ty);
}
unsigned DataLayout::getABITypeAlignment(Type *Ty) const {
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TypeSize.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
const Twine &Name,
Instruction *InsertBefore)
: Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(),
- cast<VectorType>(Mask->getType())->getNumElements()),
+ cast<VectorType>(Mask->getType())->getElementCount()),
ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this),
const Twine &Name,
BasicBlock *InsertAtEnd)
: Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(),
- cast<VectorType>(Mask->getType())->getNumElements()),
+ cast<VectorType>(Mask->getType())->getElementCount()),
ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this),
}
// Get the bit sizes, we'll need these
- unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
- unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
+ auto SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
+ auto DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
// Run through the possibilities ...
if (DestTy->isIntegerTy()) { // Casting to integral
if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) {
if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy)) {
- if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
+ if (SrcVecTy->getElementCount() == DestVecTy->getElementCount()) {
// An element by element cast. Valid if casting the elements is valid.
SrcTy = SrcVecTy->getElementType();
DestTy = DestVecTy->getElementType();
}
}
- unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
- unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
+ auto SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
+ auto DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
// Could still have vectors of pointers if the number of elements doesn't
// match
- if (SrcBits == 0 || DestBits == 0)
+ if (SrcBits.getKnownMinSize() == 0 || DestBits.getKnownMinSize() == 0)
return false;
if (SrcBits != DestBits)
#include "llvm/Support/Casting.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <utility>
return false;
}
-unsigned Type::getPrimitiveSizeInBits() const {
+TypeSize Type::getPrimitiveSizeInBits() const {
switch (getTypeID()) {
- case Type::HalfTyID: return 16;
- case Type::FloatTyID: return 32;
- case Type::DoubleTyID: return 64;
- case Type::X86_FP80TyID: return 80;
- case Type::FP128TyID: return 128;
- case Type::PPC_FP128TyID: return 128;
- case Type::X86_MMXTyID: return 64;
- case Type::IntegerTyID: return cast<IntegerType>(this)->getBitWidth();
- case Type::VectorTyID: return cast<VectorType>(this)->getBitWidth();
- default: return 0;
+ case Type::HalfTyID: return TypeSize::Fixed(16);
+ case Type::FloatTyID: return TypeSize::Fixed(32);
+ case Type::DoubleTyID: return TypeSize::Fixed(64);
+ case Type::X86_FP80TyID: return TypeSize::Fixed(80);
+ case Type::FP128TyID: return TypeSize::Fixed(128);
+ case Type::PPC_FP128TyID: return TypeSize::Fixed(128);
+ case Type::X86_MMXTyID: return TypeSize::Fixed(64);
+ case Type::IntegerTyID:
+ return TypeSize::Fixed(cast<IntegerType>(this)->getBitWidth());
+ case Type::VectorTyID: {
+ const VectorType *VTy = cast<VectorType>(this);
+ return TypeSize(VTy->getBitWidth(), VTy->isScalable());
+ }
+ default: return TypeSize::Fixed(0);
}
}
// Get the shift amount based on the scaling factor:
// log2(sizeof(IdxTy)) - log2(8).
uint64_t ShiftAmt =
- countTrailingZeros(DL.getTypeStoreSizeInBits(IdxTy)) - 3;
+ countTrailingZeros(DL.getTypeStoreSizeInBits(IdxTy).getFixedSize()) - 3;
// Is the constant foldable in the shift of the addressing mode?
// I.e., shift amount is between 1 and 4 inclusive.
if (ShiftAmt == 0 || ShiftAmt > 4)
std::tie(UsedI, I) = Uses.pop_back_val();
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
- Size = std::max(Size, DL.getTypeStoreSize(LI->getType()));
+ Size = std::max(Size,
+ DL.getTypeStoreSize(LI->getType()).getFixedSize());
continue;
}
if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
Value *Op = SI->getOperand(0);
if (Op == UsedI)
return SI;
- Size = std::max(Size, DL.getTypeStoreSize(Op->getType()));
+ Size = std::max(Size,
+ DL.getTypeStoreSize(Op->getType()).getFixedSize());
continue;
}
--- /dev/null
+; RUN: opt -S -verify < %s | FileCheck %s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+;; Check supported instructions are accepted without dropping 'vscale'.
+;; Same order as the LangRef
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Unary Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+define <vscale x 2 x double> @fneg(<vscale x 2 x double> %val) {
+; CHECK-LABEL: @fneg
+; CHECK: %r = fneg <vscale x 2 x double> %val
+; CHECK-NEXT: ret <vscale x 2 x double> %r
+ %r = fneg <vscale x 2 x double> %val
+ ret <vscale x 2 x double> %r
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Binary Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <vscale x 8 x i16> @add(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) {
+; CHECK-LABEL: @add
+; CHECK: %r = add <vscale x 8 x i16> %a, %b
+; CHECK-NEXT: ret <vscale x 8 x i16> %r
+ %r = add <vscale x 8 x i16> %a, %b
+ ret <vscale x 8 x i16> %r
+}
+
+define <vscale x 4 x float> @fadd(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: @fadd
+; CHECK: %r = fadd <vscale x 4 x float> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = fadd <vscale x 4 x float> %a, %b
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 4 x i32> @sub(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @sub
+; CHECK: %r = sub <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = sub <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x float> @fsub(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: @fsub
+; CHECK: %r = fsub <vscale x 4 x float> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = fsub <vscale x 4 x float> %a, %b
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 4 x i32> @mul(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @mul
+; CHECK: %r = mul <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = mul <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x float> @fmul(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: @fmul
+; CHECK: %r = fmul <vscale x 4 x float> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = fmul <vscale x 4 x float> %a, %b
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 4 x i32> @udiv(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @udiv
+; CHECK: %r = udiv <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = udiv <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @sdiv(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @sdiv
+; CHECK: %r = sdiv <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = sdiv <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x float> @fdiv(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: @fdiv
+; CHECK: %r = fdiv <vscale x 4 x float> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = fdiv <vscale x 4 x float> %a, %b
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 4 x i32> @urem(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @urem
+; CHECK: %r = urem <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = urem <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @srem(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @srem
+; CHECK: %r = srem <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = srem <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x float> @frem(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: @frem
+; CHECK: %r = frem <vscale x 4 x float> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = frem <vscale x 4 x float> %a, %b
+ ret <vscale x 4 x float> %r
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Bitwise Binary Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <vscale x 4 x i32> @shl(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @shl
+; CHECK: %r = shl <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = shl <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @lshr(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @lshr
+; CHECK: %r = lshr <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = lshr <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @ashr(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @ashr
+; CHECK: %r = ashr <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = ashr <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @and(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @and
+; CHECK: %r = and <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = and <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @or(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @or
+; CHECK: %r = or <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = or <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @xor(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @xor
+; CHECK: %r = xor <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = xor <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i32> %r
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Vector Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define i64 @extractelement(<vscale x 2 x i64> %val) {
+; CHECK-LABEL: @extractelement
+; CHECK: %r = extractelement <vscale x 2 x i64> %val, i32 0
+; CHECK-NEXT: ret i64 %r
+ %r = extractelement <vscale x 2 x i64> %val, i32 0
+ ret i64 %r
+}
+
+define <vscale x 16 x i8> @insertelement(<vscale x 16 x i8> %vec, i8 %ins) {
+; CHECK-LABEL: @insertelement
+; CHECK: %r = insertelement <vscale x 16 x i8> %vec, i8 %ins, i32 0
+; CHECK-NEXT: ret <vscale x 16 x i8> %r
+ %r = insertelement <vscale x 16 x i8> %vec, i8 %ins, i32 0
+ ret <vscale x 16 x i8> %r
+}
+
+define <vscale x 8 x half> @shufflevector(half %val) {
+; CHECK-LABEL: @shufflevector
+; CHECK: %insvec = insertelement <vscale x 8 x half> undef, half %val, i32 0
+; CHECK-NEXT: %r = shufflevector <vscale x 8 x half> %insvec, <vscale x 8 x half> undef, <vscale x 8 x i32> zeroinitializer
+; CHECK-NEXT: ret <vscale x 8 x half> %r
+ %insvec = insertelement <vscale x 8 x half> undef, half %val, i32 0
+ %r = shufflevector <vscale x 8 x half> %insvec, <vscale x 8 x half> undef, <vscale x 8 x i32> zeroinitializer
+ ret <vscale x 8 x half> %r
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Memory Access and Addressing Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define void @alloca() {
+; CHECK-LABEL: @alloca
+; CHECK: %vec = alloca <vscale x 4 x i32>
+; CHECK-NEXT: ret void
+ %vec = alloca <vscale x 4 x i32>
+ ret void
+}
+
+define <vscale x 2 x double> @load(<vscale x 2 x double>* %ptr) {
+; CHECK-LABEL: @load
+; CHECK: %r = load <vscale x 2 x double>, <vscale x 2 x double>* %ptr
+; CHECK-NEXT: ret <vscale x 2 x double> %r
+ %r = load <vscale x 2 x double>, <vscale x 2 x double>* %ptr
+ ret <vscale x 2 x double> %r
+}
+
+define void @store(<vscale x 4 x i32> %data, <vscale x 4 x i32>* %ptr) {
+; CHECK-LABEL: @store
+; CHECK: store <vscale x 4 x i32> %data, <vscale x 4 x i32>* %ptr
+; CHECK-NEXT: ret void
+ store <vscale x 4 x i32> %data, <vscale x 4 x i32>* %ptr
+ ret void
+}
+
+define <vscale x 4 x float>* @getelementptr(<vscale x 4 x float>* %base) {
+; CHECK-LABEL: @getelementptr
+; CHECK: %r = getelementptr <vscale x 4 x float>, <vscale x 4 x float>* %base, i64 0
+; CHECK-NEXT: ret <vscale x 4 x float>* %r
+ %r = getelementptr <vscale x 4 x float>, <vscale x 4 x float>* %base, i64 0
+ ret <vscale x 4 x float>* %r
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Conversion Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <vscale x 4 x i32> @truncto(<vscale x 4 x i64> %val) {
+; CHECK-LABEL: @truncto
+; CHECK: %r = trunc <vscale x 4 x i64> %val to <vscale x 4 x i32>
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = trunc <vscale x 4 x i64> %val to <vscale x 4 x i32>
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 2 x i64> @zextto(<vscale x 2 x i16> %val) {
+; CHECK-LABEL: @zextto
+; CHECK: %r = zext <vscale x 2 x i16> %val to <vscale x 2 x i64>
+; CHECK-NEXT: ret <vscale x 2 x i64> %r
+ %r = zext <vscale x 2 x i16> %val to <vscale x 2 x i64>
+ ret <vscale x 2 x i64> %r
+}
+
+define <vscale x 4 x i32> @sextto(<vscale x 4 x i8> %val) {
+; CHECK-LABEL: @sextto
+; CHECK: %r = sext <vscale x 4 x i8> %val to <vscale x 4 x i32>
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = sext <vscale x 4 x i8> %val to <vscale x 4 x i32>
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x half> @fptruncto(<vscale x 4 x float> %val) {
+; CHECK-LABEL: @fptruncto
+; CHECK: %r = fptrunc <vscale x 4 x float> %val to <vscale x 4 x half>
+; CHECK-NEXT: ret <vscale x 4 x half> %r
+ %r = fptrunc <vscale x 4 x float> %val to <vscale x 4 x half>
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 2 x double> @fpextto(<vscale x 2 x half> %val) {
+; CHECK-LABEL: @fpextto
+; CHECK: %r = fpext <vscale x 2 x half> %val to <vscale x 2 x double>
+; CHECK-NEXT: ret <vscale x 2 x double> %r
+ %r = fpext <vscale x 2 x half> %val to <vscale x 2 x double>
+ ret <vscale x 2 x double> %r
+}
+
+define <vscale x 4 x i32> @fptouito(<vscale x 4 x float> %val) {
+; CHECK-LABEL: @fptoui
+; CHECK: %r = fptoui <vscale x 4 x float> %val to <vscale x 4 x i32>
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = fptoui <vscale x 4 x float> %val to <vscale x 4 x i32>
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x i32> @fptosito(<vscale x 4 x float> %val) {
+; CHECK-LABEL: @fptosi
+; CHECK: %r = fptosi <vscale x 4 x float> %val to <vscale x 4 x i32>
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = fptosi <vscale x 4 x float> %val to <vscale x 4 x i32>
+ ret <vscale x 4 x i32> %r
+}
+
+define <vscale x 4 x float> @uitofpto(<vscale x 4 x i32> %val) {
+; CHECK-LABEL: @uitofp
+; CHECK: %r = uitofp <vscale x 4 x i32> %val to <vscale x 4 x float>
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = uitofp <vscale x 4 x i32> %val to <vscale x 4 x float>
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 4 x float> @sitofpto(<vscale x 4 x i32> %val) {
+; CHECK-LABEL: @sitofp
+; CHECK: %r = sitofp <vscale x 4 x i32> %val to <vscale x 4 x float>
+; CHECK-NEXT: ret <vscale x 4 x float> %r
+ %r = sitofp <vscale x 4 x i32> %val to <vscale x 4 x float>
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x i64> @ptrtointto(<vscale x 2 x i32*> %val) {
+; CHECK-LABEL: @ptrtointto
+; CHECK: %r = ptrtoint <vscale x 2 x i32*> %val to <vscale x 2 x i64>
+; CHECK-NEXT: ret <vscale x 2 x i64> %r
+ %r = ptrtoint <vscale x 2 x i32*> %val to <vscale x 2 x i64>
+ ret <vscale x 2 x i64> %r
+}
+
+define <vscale x 2 x i32*> @inttoptrto(<vscale x 2 x i64> %val) {
+; CHECK-LABEL: @inttoptrto
+; CHECK: %r = inttoptr <vscale x 2 x i64> %val to <vscale x 2 x i32*>
+; CHECK-NEXT: ret <vscale x 2 x i32*> %r
+ %r = inttoptr <vscale x 2 x i64> %val to <vscale x 2 x i32*>
+ ret <vscale x 2 x i32*> %r
+}
+
+define <vscale x 2 x i64> @bitcastto(<vscale x 2 x double> %a) {
+; CHECK-LABEL: @bitcast
+; CHECK: %r = bitcast <vscale x 2 x double> %a to <vscale x 2 x i64>
+; CHECK-NEXT: ret <vscale x 2 x i64> %r
+ %r = bitcast <vscale x 2 x double> %a to <vscale x 2 x i64>
+ ret <vscale x 2 x i64> %r
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Other Operations
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <vscale x 4 x i1> @icmp(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: @icmp
+; CHECK: %r = icmp eq <vscale x 4 x i32> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i1> %r
+ %r = icmp eq <vscale x 4 x i32> %a, %b
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 4 x i1> @fcmp(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: @fcmp
+; CHECK: %r = fcmp une <vscale x 4 x float> %a, %b
+; CHECK-NEXT: ret <vscale x 4 x i1> %r
+ %r = fcmp une <vscale x 4 x float> %a, %b
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 16 x i8> @phi(<vscale x 16 x i8> %a, i32 %val) {
+; CHECK-LABEL: @phi
+; CHECK: %r = phi <vscale x 16 x i8> [ %a, %entry ], [ %added, %iszero ]
+; CHECK-NEXT: ret <vscale x 16 x i8> %r
+entry:
+ %cmp = icmp eq i32 %val, 0
+ br i1 %cmp, label %iszero, label %end
+
+iszero:
+ %ins = insertelement <vscale x 16 x i8> undef, i8 1, i32 0
+ %splatone = shufflevector <vscale x 16 x i8> %ins, <vscale x 16 x i8> undef, <vscale x 16 x i32> zeroinitializer
+ %added = add <vscale x 16 x i8> %a, %splatone
+ br label %end
+
+end:
+ %r = phi <vscale x 16 x i8> [ %a, %entry ], [ %added, %iszero ]
+ ret <vscale x 16 x i8> %r
+}
+
+define <vscale x 8 x half> @select(<vscale x 8 x half> %a, <vscale x 8 x half> %b, <vscale x 8 x i1> %sval) {
+; CHECK-LABEL: @select
+; CHECK: %r = select <vscale x 8 x i1> %sval, <vscale x 8 x half> %a, <vscale x 8 x half> %b
+; CHECK-NEXT: ret <vscale x 8 x half> %r
+ %r = select <vscale x 8 x i1> %sval, <vscale x 8 x half> %a, <vscale x 8 x half> %b
+ ret <vscale x 8 x half> %r
+}
+
+declare <vscale x 4 x i32> @callee(<vscale x 4 x i32>)
+define <vscale x 4 x i32> @call(<vscale x 4 x i32> %val) {
+; CHECK-LABEL: @call
+; CHECK: %r = call <vscale x 4 x i32> @callee(<vscale x 4 x i32> %val)
+; CHECK-NEXT: ret <vscale x 4 x i32> %r
+ %r = call <vscale x 4 x i32> @callee(<vscale x 4 x i32> %val)
+ ret <vscale x 4 x i32> %r
+}
\ No newline at end of file
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/MachineValueType.h"
-#include "llvm/Support/ScalableSize.h"
+#include "llvm/Support/TypeSize.h"
#include "gtest/gtest.h"
using namespace llvm;
//
//===----------------------------------------------------------------------===//
+#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Support/ScalableSize.h"
+#include "llvm/Support/TypeSize.h"
#include "gtest/gtest.h"
using namespace llvm;
ASSERT_TRUE(EltCnt.Scalable);
}
+TEST(VectorTypesTest, FixedLenComparisons) {
+ LLVMContext Ctx;
+ DataLayout DL("");
+
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+ Type *Int64Ty = Type::getInt64Ty(Ctx);
+
+ VectorType *V2Int32Ty = VectorType::get(Int32Ty, 2);
+ VectorType *V4Int32Ty = VectorType::get(Int32Ty, 4);
+
+ VectorType *V2Int64Ty = VectorType::get(Int64Ty, 2);
+
+ TypeSize V2I32Len = V2Int32Ty->getPrimitiveSizeInBits();
+ EXPECT_EQ(V2I32Len.getKnownMinSize(), 64U);
+ EXPECT_FALSE(V2I32Len.isScalable());
+
+ EXPECT_LT(V2Int32Ty->getPrimitiveSizeInBits(),
+ V4Int32Ty->getPrimitiveSizeInBits());
+ EXPECT_GT(V2Int64Ty->getPrimitiveSizeInBits(),
+ V2Int32Ty->getPrimitiveSizeInBits());
+ EXPECT_EQ(V4Int32Ty->getPrimitiveSizeInBits(),
+ V2Int64Ty->getPrimitiveSizeInBits());
+ EXPECT_NE(V2Int32Ty->getPrimitiveSizeInBits(),
+ V2Int64Ty->getPrimitiveSizeInBits());
+
+ // Check that a fixed-only comparison works for fixed size vectors.
+ EXPECT_EQ(V2Int64Ty->getPrimitiveSizeInBits().getFixedSize(),
+ V4Int32Ty->getPrimitiveSizeInBits().getFixedSize());
+
+ // Check the DataLayout interfaces.
+ EXPECT_EQ(DL.getTypeSizeInBits(V2Int64Ty),
+ DL.getTypeSizeInBits(V4Int32Ty));
+ EXPECT_EQ(DL.getTypeSizeInBits(V2Int32Ty), 64U);
+ EXPECT_EQ(DL.getTypeSizeInBits(V2Int64Ty), 128U);
+ EXPECT_EQ(DL.getTypeStoreSize(V2Int64Ty),
+ DL.getTypeStoreSize(V4Int32Ty));
+ EXPECT_NE(DL.getTypeStoreSizeInBits(V2Int32Ty),
+ DL.getTypeStoreSizeInBits(V2Int64Ty));
+ EXPECT_EQ(DL.getTypeStoreSizeInBits(V2Int32Ty), 64U);
+ EXPECT_EQ(DL.getTypeStoreSize(V2Int64Ty), 16U);
+ EXPECT_EQ(DL.getTypeAllocSize(V4Int32Ty),
+ DL.getTypeAllocSize(V2Int64Ty));
+ EXPECT_NE(DL.getTypeAllocSizeInBits(V2Int32Ty),
+ DL.getTypeAllocSizeInBits(V2Int64Ty));
+ EXPECT_EQ(DL.getTypeAllocSizeInBits(V4Int32Ty), 128U);
+ EXPECT_EQ(DL.getTypeAllocSize(V2Int32Ty), 8U);
+ ASSERT_TRUE(DL.typeSizeEqualsStoreSize(V4Int32Ty));
+}
+
+TEST(VectorTypesTest, ScalableComparisons) {
+ LLVMContext Ctx;
+ DataLayout DL("");
+
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+ Type *Int64Ty = Type::getInt64Ty(Ctx);
+
+ VectorType *ScV2Int32Ty = VectorType::get(Int32Ty, {2, true});
+ VectorType *ScV4Int32Ty = VectorType::get(Int32Ty, {4, true});
+
+ VectorType *ScV2Int64Ty = VectorType::get(Int64Ty, {2, true});
+
+ TypeSize ScV2I32Len = ScV2Int32Ty->getPrimitiveSizeInBits();
+ EXPECT_EQ(ScV2I32Len.getKnownMinSize(), 64U);
+ EXPECT_TRUE(ScV2I32Len.isScalable());
+
+ EXPECT_LT(ScV2Int32Ty->getPrimitiveSizeInBits(),
+ ScV4Int32Ty->getPrimitiveSizeInBits());
+ EXPECT_GT(ScV2Int64Ty->getPrimitiveSizeInBits(),
+ ScV2Int32Ty->getPrimitiveSizeInBits());
+ EXPECT_EQ(ScV4Int32Ty->getPrimitiveSizeInBits(),
+ ScV2Int64Ty->getPrimitiveSizeInBits());
+ EXPECT_NE(ScV2Int32Ty->getPrimitiveSizeInBits(),
+ ScV2Int64Ty->getPrimitiveSizeInBits());
+
+ // Check the DataLayout interfaces.
+ EXPECT_EQ(DL.getTypeSizeInBits(ScV2Int64Ty),
+ DL.getTypeSizeInBits(ScV4Int32Ty));
+ EXPECT_EQ(DL.getTypeSizeInBits(ScV2Int32Ty).getKnownMinSize(), 64U);
+ EXPECT_EQ(DL.getTypeStoreSize(ScV2Int64Ty),
+ DL.getTypeStoreSize(ScV4Int32Ty));
+ EXPECT_NE(DL.getTypeStoreSizeInBits(ScV2Int32Ty),
+ DL.getTypeStoreSizeInBits(ScV2Int64Ty));
+ EXPECT_EQ(DL.getTypeStoreSizeInBits(ScV2Int32Ty).getKnownMinSize(), 64U);
+ EXPECT_EQ(DL.getTypeStoreSize(ScV2Int64Ty).getKnownMinSize(), 16U);
+ EXPECT_EQ(DL.getTypeAllocSize(ScV4Int32Ty),
+ DL.getTypeAllocSize(ScV2Int64Ty));
+ EXPECT_NE(DL.getTypeAllocSizeInBits(ScV2Int32Ty),
+ DL.getTypeAllocSizeInBits(ScV2Int64Ty));
+ EXPECT_EQ(DL.getTypeAllocSizeInBits(ScV4Int32Ty).getKnownMinSize(), 128U);
+ EXPECT_EQ(DL.getTypeAllocSize(ScV2Int32Ty).getKnownMinSize(), 8U);
+ ASSERT_TRUE(DL.typeSizeEqualsStoreSize(ScV4Int32Ty));
+}
+
+TEST(VectorTypesTest, CrossComparisons) {
+ LLVMContext Ctx;
+
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+
+ VectorType *V4Int32Ty = VectorType::get(Int32Ty, {4, false});
+ VectorType *ScV4Int32Ty = VectorType::get(Int32Ty, {4, true});
+
+ // Even though the minimum size is the same, a scalable vector could be
+ // larger so we don't consider them to be the same size.
+ EXPECT_NE(V4Int32Ty->getPrimitiveSizeInBits(),
+ ScV4Int32Ty->getPrimitiveSizeInBits());
+ // If we are only checking the minimum, then they are the same size.
+ EXPECT_EQ(V4Int32Ty->getPrimitiveSizeInBits().getKnownMinSize(),
+ ScV4Int32Ty->getPrimitiveSizeInBits().getKnownMinSize());
+
+ // We can't use ordering comparisons (<,<=,>,>=) between scalable and
+ // non-scalable vector sizes.
+}
+
} // end anonymous namespace