llvm.org GIT mirror llvm / 6fea0a2
Scalable Vector IR Type with further LTO fixes Reintroduces the scalable vector IR type from D32530, after it was reverted a couple of times due to increasing chromium LTO build times. This latest incarnation removes the walk over aggregate types from the verifier entirely, in favor of rejecting scalable vectors in the isValidElementType methods in ArrayType and StructType. This removes the 70% degradation observed with the second repro tarball from PR42210. Reviewers: thakis, hans, rengolin, sdesmalen Reviewed By: sdesmalen Differential Revision: https://reviews.llvm.org/D64079 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365203 91177308-0d34-0410-b5e6-96231b3b80d8 Graham Hunter a month ago
20 changed file(s) with 398 addition(s) and 40 deletion(s). Raw diff Collapse all Expand all
673673
674674 Variables and aliases can have a
675675 :ref:`Thread Local Storage Model `.
676
677 :ref:`Scalable vectors ` cannot be global variables or members of
678 structs or arrays because their size is unknown at compile time.
676679
677680 Syntax::
678681
27412744 A vector type is a simple derived type that represents a vector of
27422745 elements. Vector types are used when multiple primitive data are
27432746 operated in parallel using a single instruction (SIMD). A vector type
2744 requires a size (number of elements) and an underlying primitive data
2745 type. Vector types are considered :ref:`first class `.
2747 requires a size (number of elements), an underlying primitive data type,
2748 and a scalable property to represent vectors where the exact hardware
2749 vector length is unknown at compile time. Vector types are considered
2750 :ref:`first class `.
27462751
27472752 :Syntax:
27482753
27492754 ::
27502755
2751 < <# elements> x >
2756 < <# elements> x > ; Fixed-length vector
2757 < vscale x <# elements> x > ; Scalable vector
27522758
27532759 The number of elements is a constant integer value larger than 0;
27542760 elementtype may be any integer, floating-point or pointer type. Vectors
2755 of size zero are not allowed.
2761 of size zero are not allowed. For scalable vectors, the total number of
2762 elements is a constant multiple (called vscale) of the specified number
2763 of elements; vscale is a positive integer that is unknown at compile time
2764 and the same hardware-dependent constant for all scalable vectors at run
2765 time. The size of a specific scalable vector type is thus constant within
2766 IR, even if the exact size in bytes cannot be determined until run time.
27562767
27572768 :Examples:
27582769
2759 +-------------------+--------------------------------------------------+
2760 | ``<4 x i32>`` | Vector of 4 32-bit integer values. |
2761 +-------------------+--------------------------------------------------+
2762 | ``<8 x float>`` | Vector of 8 32-bit floating-point values. |
2763 +-------------------+--------------------------------------------------+
2764 | ``<2 x i64>`` | Vector of 2 64-bit integer values. |
2765 +-------------------+--------------------------------------------------+
2766 | ``<4 x i64*>`` | Vector of 4 pointers to 64-bit integer values. |
2767 +-------------------+--------------------------------------------------+
2770 +------------------------+----------------------------------------------------+
2771 | ``<4 x i32>`` | Vector of 4 32-bit integer values. |
2772 +------------------------+----------------------------------------------------+
2773 | ``<8 x float>`` | Vector of 8 32-bit floating-point values. |
2774 +------------------------+----------------------------------------------------+
2775 | ``<2 x i64>`` | Vector of 2 64-bit integer values. |
2776 +------------------------+----------------------------------------------------+
2777 | ``<4 x i64*>`` | Vector of 4 pointers to 64-bit integer values. |
2778 +------------------------+----------------------------------------------------+
2779 | ```` | Vector with a multiple of 4 32-bit integer values. |
2780 +------------------------+----------------------------------------------------+
27682781
27692782 .. _t_label:
27702783
81878200 ::
81888201
81898202 = extractelement > , ; yields
8203 = extractelement > , ; yields
81908204
81918205 Overview:
81928206 """""""""
82078221
82088222 The result is a scalar of the same type as the element type of ``val``.
82098223 Its value is the value at position ``idx`` of ``val``. If ``idx``
8210 exceeds the length of ``val``, the result is a
8224 exceeds the length of ``val`` for a fixed-length vector, the result is a
8225 :ref:`poison value `. For a scalable vector, if the value
8226 of ``idx`` exceeds the runtime length of the vector, the result is a
82118227 :ref:`poison value `.
82128228
82138229 Example:
82288244 ::
82298245
82308246 = insertelement > , , ; yields >
8247 = insertelement > , , ; yields >
82318248
82328249 Overview:
82338250 """""""""
82498266
82508267 The result is a vector of the same type as ``val``. Its element values
82518268 are those of ``val`` except at position ``idx``, where it gets the value
8252 ``elt``. If ``idx`` exceeds the length of ``val``, the result
8269 ``elt``. If ``idx`` exceeds the length of ``val`` for a fixed-length vector,
8270 the result is a :ref:`poison value `. For a scalable vector,
8271 if the value of ``idx`` exceeds the runtime length of the vector, the result
82538272 is a :ref:`poison value `.
82548273
82558274 Example:
82708289 ::
82718290
82728291 = shufflevector > , > , ; yields >
8292 = shufflevector > , > v2, ; yields >
82738293
82748294 Overview:
82758295 """""""""
83008320 undef. If any element of the mask operand is undef, that element of the
83018321 result is undef. If the shuffle mask selects an undef element from one
83028322 of the input vectors, the resulting element is undef.
8323
8324 For scalable vectors, the only valid mask values at present are
8325 ``zeroinitializer`` and ``undef``, since we cannot write all indices as
8326 literals for a vector with a length unknown at compile time.
83038327
83048328 Example:
83058329 """"""""
1616 #include "llvm/ADT/Hashing.h"
1717 #include "llvm/ADT/StringRef.h"
1818 #include "llvm/Support/PointerLikeTypeTraits.h"
19 #include "llvm/Support/ScalableSize.h"
1920 #include
2021 #include
2122 #include
267268 static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
268269 };
269270
271 template <> struct DenseMapInfo {
272 static inline ElementCount getEmptyKey() { return {~0U, true}; }
273 static inline ElementCount getTombstoneKey() { return {~0U - 1, false}; }
274 static unsigned getHashValue(const ElementCount& EltCnt) {
275 if (EltCnt.Scalable)
276 return (EltCnt.Min * 37U) - 1U;
277
278 return EltCnt.Min * 37U;
279 }
280
281 static bool isEqual(const ElementCount& LHS, const ElementCount& RHS) {
282 return LHS == RHS;
283 }
284 };
285
270286 } // end namespace llvm
271287
272288 #endif // LLVM_ADT_DENSEMAPINFO_H
2222 #include "llvm/IR/Type.h"
2323 #include "llvm/Support/Casting.h"
2424 #include "llvm/Support/Compiler.h"
25 #include "llvm/Support/ScalableSize.h"
2526 #include
2627 #include
2728
386387 SequentialType(const SequentialType &) = delete;
387388 SequentialType &operator=(const SequentialType &) = delete;
388389
390 /// For scalable vectors, this will return the minimum number of elements
391 /// in the vector.
389392 uint64_t getNumElements() const { return NumElements; }
390393 Type *getElementType() const { return ContainedType; }
391394
421424
422425 /// Class to represent vector types.
423426 class VectorType : public SequentialType {
424 VectorType(Type *ElType, unsigned NumEl);
427 /// A fully specified VectorType is of the form . 'n' is the
428 /// minimum number of elements of type Ty contained within the vector, and
429 /// 'vscale x' indicates that the total element count is an integer multiple
430 /// of 'n', where the multiple is either guaranteed to be one, or is
431 /// statically unknown at compile time.
432 ///
433 /// If the multiple is known to be 1, then the extra term is discarded in
434 /// textual IR:
435 ///
436 /// <4 x i32> - a vector containing 4 i32s
437 /// - a vector containing an unknown integer multiple
438 /// of 4 i32s
439
440 VectorType(Type *ElType, unsigned NumEl, bool Scalable = false);
441 VectorType(Type *ElType, ElementCount EC);
442
443 // If true, the total number of elements is an unknown multiple of the
444 // minimum 'NumElements' from SequentialType. Otherwise the total number
445 // of elements is exactly equal to 'NumElements'.
446 bool Scalable;
425447
426448 public:
427449 VectorType(const VectorType &) = delete;
428450 VectorType &operator=(const VectorType &) = delete;
429451
430452 /// This static method is the primary way to construct an VectorType.
431 static VectorType *get(Type *ElementType, unsigned NumElements);
453 static VectorType *get(Type *ElementType, ElementCount EC);
454 static VectorType *get(Type *ElementType, unsigned NumElements,
455 bool Scalable = false) {
456 return VectorType::get(ElementType, {NumElements, Scalable});
457 }
432458
433459 /// This static method gets a VectorType with the same number of elements as
434460 /// the input type, and the element type is an integer type of the same width
437463 unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
438464 assert(EltBits && "Element size must be of a non-zero size");
439465 Type *EltTy = IntegerType::get(VTy->getContext(), EltBits);
440 return VectorType::get(EltTy, VTy->getNumElements());
466 return VectorType::get(EltTy, VTy->getElementCount());
441467 }
442468
443469 /// This static method is like getInteger except that the element types are
445471 static VectorType *getExtendedElementVectorType(VectorType *VTy) {
446472 unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
447473 Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2);
448 return VectorType::get(EltTy, VTy->getNumElements());
474 return VectorType::get(EltTy, VTy->getElementCount());
449475 }
450476
451477 /// This static method is like getInteger except that the element types are
455481 assert((EltBits & 1) == 0 &&
456482 "Cannot truncate vector element with odd bit-width");
457483 Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2);
458 return VectorType::get(EltTy, VTy->getNumElements());
484 return VectorType::get(EltTy, VTy->getElementCount());
459485 }
460486
461487 /// This static method returns a VectorType with half as many elements as the
462488 /// input type and the same element type.
463489 static VectorType *getHalfElementsVectorType(VectorType *VTy) {
464 unsigned NumElts = VTy->getNumElements();
465 assert ((NumElts & 1) == 0 &&
490 auto EltCnt = VTy->getElementCount();
491 assert ((EltCnt.Min & 1) == 0 &&
466492 "Cannot halve vector with odd number of elements.");
467 return VectorType::get(VTy->getElementType(), NumElts/2);
493 return VectorType::get(VTy->getElementType(), EltCnt/2);
468494 }
469495
470496 /// This static method returns a VectorType with twice as many elements as the
471497 /// input type and the same element type.
472498 static VectorType *getDoubleElementsVectorType(VectorType *VTy) {
473 unsigned NumElts = VTy->getNumElements();
474 return VectorType::get(VTy->getElementType(), NumElts*2);
499 auto EltCnt = VTy->getElementCount();
500 assert((VTy->getNumElements() * 2ull) <= UINT_MAX &&
501 "Too many elements in vector");
502 return VectorType::get(VTy->getElementType(), EltCnt*2);
475503 }
476504
477505 /// Return true if the specified type is valid as a element type.
478506 static bool isValidElementType(Type *ElemTy);
479507
480 /// Return the number of bits in the Vector type.
508 /// Return an ElementCount instance to represent the (possibly scalable)
509 /// number of elements in the vector.
510 ElementCount getElementCount() const {
511 uint64_t MinimumEltCnt = getNumElements();
512 assert(MinimumEltCnt <= UINT_MAX && "Too many elements in vector");
513 return { (unsigned)MinimumEltCnt, Scalable };
514 }
515
516 /// Returns whether or not this is a scalable vector (meaning the total
517 /// element count is a multiple of the minimum).
518 bool isScalable() const {
519 return Scalable;
520 }
521
522 /// Return the minimum number of bits in the Vector type.
481523 /// Returns zero when the vector is a vector of pointers.
482524 unsigned getBitWidth() const {
483525 return getNumElements() * getElementType()->getPrimitiveSizeInBits();
491533
492534 unsigned Type::getVectorNumElements() const {
493535 return cast(this)->getNumElements();
536 }
537
538 bool Type::getVectorIsScalable() const {
539 return cast(this)->isScalable();
494540 }
495541
496542 /// Class to represent pointers.
365365 return ContainedTys[0];
366366 }
367367
368 inline bool getVectorIsScalable() const;
368369 inline unsigned getVectorNumElements() const;
369370 Type *getVectorElementType() const {
370371 assert(getTypeID() == VectorTyID);
0 //===- ScalableSize.h - Scalable vector size info ---------------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file provides a struct that can be used to query the size of IR types
9 // which may be scalable vectors. It provides convenience operators so that
10 // it can be used in much the same way as a single scalar value.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_SUPPORT_SCALABLESIZE_H
15 #define LLVM_SUPPORT_SCALABLESIZE_H
16
17 namespace llvm {
18
19 class ElementCount {
20 public:
21 unsigned Min; // Minimum number of vector elements.
22 bool Scalable; // If true, NumElements is a multiple of 'Min' determined
23 // at runtime rather than compile time.
24
25 ElementCount(unsigned Min, bool Scalable)
26 : Min(Min), Scalable(Scalable) {}
27
28 ElementCount operator*(unsigned RHS) {
29 return { Min * RHS, Scalable };
30 }
31 ElementCount operator/(unsigned RHS) {
32 return { Min / RHS, Scalable };
33 }
34
35 bool operator==(const ElementCount& RHS) const {
36 return Min == RHS.Min && Scalable == RHS.Scalable;
37 }
38 };
39
40 } // end namespace llvm
41
42 #endif // LLVM_SUPPORT_SCALABLESIZE_H
707707 KEYWORD(xchg); KEYWORD(nand); KEYWORD(max); KEYWORD(min); KEYWORD(umax);
708708 KEYWORD(umin);
709709
710 KEYWORD(vscale);
710711 KEYWORD(x);
711712 KEYWORD(blockaddress);
712713
27462746 /// Type
27472747 /// ::= '[' APSINTVAL 'x' Types ']'
27482748 /// ::= '<' APSINTVAL 'x' Types '>'
2749 /// ::= '<' 'vscale' 'x' APSINTVAL 'x' Types '>'
27492750 bool LLParser::ParseArrayVectorType(Type *&Result, bool isVector) {
2751 bool Scalable = false;
2752
2753 if (isVector && Lex.getKind() == lltok::kw_vscale) {
2754 Lex.Lex(); // consume the 'vscale'
2755 if (ParseToken(lltok::kw_x, "expected 'x' after vscale"))
2756 return true;
2757
2758 Scalable = true;
2759 }
2760
27502761 if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() ||
27512762 Lex.getAPSIntVal().getBitWidth() > 64)
27522763 return TokError("expected number in address space");
27732784 return Error(SizeLoc, "size too large for vector");
27742785 if (!VectorType::isValidElementType(EltTy))
27752786 return Error(TypeLoc, "invalid vector element type");
2776 Result = VectorType::get(EltTy, unsigned(Size));
2787 Result = VectorType::get(EltTy, unsigned(Size), Scalable);
27772788 } else {
27782789 if (!ArrayType::isValidElementType(EltTy))
27792790 return Error(TypeLoc, "invalid array element type");
3636 bar, // |
3737 colon, // :
3838
39 kw_vscale,
3940 kw_x,
4041 kw_true,
4142 kw_false,
18771877 return error("Invalid type");
18781878 ResultTy = ArrayType::get(ResultTy, Record[0]);
18791879 break;
1880 case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
1880 case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty] or
1881 // [numelts, eltty, scalable]
18811882 if (Record.size() < 2)
18821883 return error("Invalid record");
18831884 if (Record[0] == 0)
18851886 ResultTy = getTypeByID(Record[1]);
18861887 if (!ResultTy || !StructType::isValidElementType(ResultTy))
18871888 return error("Invalid type");
1888 ResultTy = VectorType::get(ResultTy, Record[0]);
1889 bool Scalable = Record.size() > 2 ? Record[2] : false;
1890 ResultTy = VectorType::get(ResultTy, Record[0], Scalable);
18891891 break;
18901892 }
18911893
940940 }
941941 case Type::VectorTyID: {
942942 VectorType *VT = cast(T);
943 // VECTOR [numelts, eltty]
943 // VECTOR [numelts, eltty] or
944 // [numelts, eltty, scalable]
944945 Code = bitc::TYPE_CODE_VECTOR;
945946 TypeVals.push_back(VT->getNumElements());
946947 TypeVals.push_back(VE.getTypeID(VT->getElementType()));
948 if (VT->isScalable())
949 TypeVals.push_back(VT->isScalable());
947950 break;
948951 }
949952 }
619619 }
620620 case Type::VectorTyID: {
621621 VectorType *PTy = cast(Ty);
622 OS << "<" << PTy->getNumElements() << " x ";
622 OS << "<";
623 if (PTy->isScalable())
624 OS << "vscale x ";
625 OS << PTy->getNumElements() << " x ";
623626 print(PTy->getElementType(), OS);
624627 OS << '>';
625628 return;
13331333 unsigned NamedStructTypesUniqueID = 0;
13341334
13351335 DenseMap, ArrayType*> ArrayTypes;
1336 DenseMapunsigned>, VectorType*> VectorTypes;
1336 DenseMapElementCount>, VectorType*> VectorTypes;
13371337 DenseMap PointerTypes; // Pointers in AddrSpace = 0
13381338 DenseMap, PointerType*> ASPointerTypes;
13391339
503503 }
504504
505505 bool StructType::isValidElementType(Type *ElemTy) {
506 if (auto *VTy = dyn_cast(ElemTy))
507 return !VTy->isScalable();
506508 return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
507509 !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() &&
508510 !ElemTy->isTokenTy();
589591 }
590592
591593 bool ArrayType::isValidElementType(Type *ElemTy) {
594 if (auto *VTy = dyn_cast(ElemTy))
595 return !VTy->isScalable();
592596 return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
593597 !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() &&
594598 !ElemTy->isTokenTy();
598602 // VectorType Implementation
599603 //===----------------------------------------------------------------------===//
600604
601 VectorType::VectorType(Type *ElType, unsigned NumEl)
602 : SequentialType(VectorTyID, ElType, NumEl) {}
603
604 VectorType *VectorType::get(Type *ElementType, unsigned NumElements) {
605 assert(NumElements > 0 && "#Elements of a VectorType must be greater than 0");
605 VectorType::VectorType(Type *ElType, ElementCount EC)
606 : SequentialType(VectorTyID, ElType, EC.Min), Scalable(EC.Scalable) {}
607
608 VectorType *VectorType::get(Type *ElementType, ElementCount EC) {
609 assert(EC.Min > 0 && "#Elements of a VectorType must be greater than 0");
606610 assert(isValidElementType(ElementType) && "Element type of a VectorType must "
607611 "be an integer, floating point, or "
608612 "pointer type.");
609613
610614 LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
611615 VectorType *&Entry = ElementType->getContext().pImpl
612 ->VectorTypes[std::make_pair(ElementType, NumElements)];
613
616 ->VectorTypes[std::make_pair(ElementType, EC)];
614617 if (!Entry)
615 Entry = new (pImpl->Alloc) VectorType(ElementType, NumElements);
618 Entry = new (pImpl->Alloc) VectorType(ElementType, EC);
616619 return Entry;
617620 }
618621
690690 "DIGlobalVariableExpression");
691691 }
692692
693 // Scalable vectors cannot be global variables, since we don't know
694 // the runtime size. If the global is a struct or an array containing
695 // scalable vectors, that will be caught by the isValidElementType methods
696 // in StructType or ArrayType instead.
697 if (auto *VTy = dyn_cast(GV.getValueType()))
698 Assert(!VTy->isScalable(), "Globals cannot contain scalable vectors", &GV);
699
693700 if (!GV.hasInitializer()) {
694701 visitGlobalValue(GV);
695702 return;
916916 ; CHECK: %t7 = alloca x86_mmx
917917 %t8 = alloca %opaquety*
918918 ; CHECK: %t8 = alloca %opaquety*
919 %t9 = alloca <4 x i32>
920 ; CHECK: %t9 = alloca <4 x i32>
921 %t10 = alloca
922 ; CHECK: %t10 = alloca
919923
920924 ret void
921925 }
0 ; RUN: not opt -S -verify < %s 2>&1 | FileCheck %s
1
2 ;; Arrays cannot contain scalable vectors; make sure we detect them even
3 ;; when nested inside other aggregates.
4
5 %ty = type { i64, [4 x ] }
6 ; CHECK: error: invalid array element type
7 ; CHECK: %ty = type { i64, [4 x ] }
0 ; RUN: not opt -S -verify < %s 2>&1 | FileCheck %s
1
2 ;; Structs cannot contain scalable vectors; make sure we detect them even
3 ;; when nested inside other aggregates.
4
5 %ty = type [2 x { i32, }]
6 ; CHECK: error: invalid element type for struct
7 ; CHECK: %ty = type [2 x { i32, }]
0 ; RUN: not opt -S -verify < %s 2>&1 | FileCheck %s
1
2 ;; Global variables cannot be scalable vectors, since we don't
3 ;; know the size at compile time.
4
5 ; CHECK: Globals cannot contain scalable vectors
6 ; CHECK-NEXT: * @ScalableVecGlobal
7 @ScalableVecGlobal = global zeroinitializer
8
9 ;; Global _pointers_ to scalable vectors are fine
10 ; CHECK-NOT: Globals cannot contain scalable vectors
11 @ScalableVecPtr = global * zeroinitializer
3636 ValueHandleTest.cpp
3737 ValueMapTest.cpp
3838 ValueTest.cpp
39 VectorTypesTest.cpp
3940 VerifierTest.cpp
4041 WaymarkTest.cpp
4142 )
0 //===--- llvm/unittest/IR/VectorTypesTest.cpp - vector types unit tests ---===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "llvm/IR/DerivedTypes.h"
9 #include "llvm/IR/LLVMContext.h"
10 #include "llvm/Support/ScalableSize.h"
11 #include "gtest/gtest.h"
12 using namespace llvm;
13
14 namespace {
15 TEST(VectorTypesTest, FixedLength) {
16 LLVMContext Ctx;
17
18 Type *Int16Ty = Type::getInt16Ty(Ctx);
19 Type *Int32Ty = Type::getInt32Ty(Ctx);
20 Type *Int64Ty = Type::getInt64Ty(Ctx);
21 Type *Float64Ty = Type::getDoubleTy(Ctx);
22
23 VectorType *V8Int32Ty = VectorType::get(Int32Ty, 8);
24 ASSERT_FALSE(V8Int32Ty->isScalable());
25 EXPECT_EQ(V8Int32Ty->getNumElements(), 8U);
26 EXPECT_EQ(V8Int32Ty->getElementType()->getScalarSizeInBits(), 32U);
27
28 VectorType *V8Int16Ty = VectorType::get(Int16Ty, {8, false});
29 ASSERT_FALSE(V8Int16Ty->isScalable());
30 EXPECT_EQ(V8Int16Ty->getNumElements(), 8U);
31 EXPECT_EQ(V8Int16Ty->getElementType()->getScalarSizeInBits(), 16U);
32
33 ElementCount EltCnt(4, false);
34 VectorType *V4Int64Ty = VectorType::get(Int64Ty, EltCnt);
35 ASSERT_FALSE(V4Int64Ty->isScalable());
36 EXPECT_EQ(V4Int64Ty->getNumElements(), 4U);
37 EXPECT_EQ(V4Int64Ty->getElementType()->getScalarSizeInBits(), 64U);
38
39 VectorType *V2Int64Ty = VectorType::get(Int64Ty, EltCnt/2);
40 ASSERT_FALSE(V2Int64Ty->isScalable());
41 EXPECT_EQ(V2Int64Ty->getNumElements(), 2U);
42 EXPECT_EQ(V2Int64Ty->getElementType()->getScalarSizeInBits(), 64U);
43
44 VectorType *V8Int64Ty = VectorType::get(Int64Ty, EltCnt*2);
45 ASSERT_FALSE(V8Int64Ty->isScalable());
46 EXPECT_EQ(V8Int64Ty->getNumElements(), 8U);
47 EXPECT_EQ(V8Int64Ty->getElementType()->getScalarSizeInBits(), 64U);
48
49 VectorType *V4Float64Ty = VectorType::get(Float64Ty, EltCnt);
50 ASSERT_FALSE(V4Float64Ty->isScalable());
51 EXPECT_EQ(V4Float64Ty->getNumElements(), 4U);
52 EXPECT_EQ(V4Float64Ty->getElementType()->getScalarSizeInBits(), 64U);
53
54 VectorType *ExtTy = VectorType::getExtendedElementVectorType(V8Int16Ty);
55 EXPECT_EQ(ExtTy, V8Int32Ty);
56 ASSERT_FALSE(ExtTy->isScalable());
57 EXPECT_EQ(ExtTy->getNumElements(), 8U);
58 EXPECT_EQ(ExtTy->getElementType()->getScalarSizeInBits(), 32U);
59
60 VectorType *TruncTy = VectorType::getTruncatedElementVectorType(V8Int32Ty);
61 EXPECT_EQ(TruncTy, V8Int16Ty);
62 ASSERT_FALSE(TruncTy->isScalable());
63 EXPECT_EQ(TruncTy->getNumElements(), 8U);
64 EXPECT_EQ(TruncTy->getElementType()->getScalarSizeInBits(), 16U);
65
66 VectorType *HalvedTy = VectorType::getHalfElementsVectorType(V4Int64Ty);
67 EXPECT_EQ(HalvedTy, V2Int64Ty);
68 ASSERT_FALSE(HalvedTy->isScalable());
69 EXPECT_EQ(HalvedTy->getNumElements(), 2U);
70 EXPECT_EQ(HalvedTy->getElementType()->getScalarSizeInBits(), 64U);
71
72 VectorType *DoubledTy = VectorType::getDoubleElementsVectorType(V4Int64Ty);
73 EXPECT_EQ(DoubledTy, V8Int64Ty);
74 ASSERT_FALSE(DoubledTy->isScalable());
75 EXPECT_EQ(DoubledTy->getNumElements(), 8U);
76 EXPECT_EQ(DoubledTy->getElementType()->getScalarSizeInBits(), 64U);
77
78 VectorType *ConvTy = VectorType::getInteger(V4Float64Ty);
79 EXPECT_EQ(ConvTy, V4Int64Ty);
80 ASSERT_FALSE(ConvTy->isScalable());
81 EXPECT_EQ(ConvTy->getNumElements(), 4U);
82 EXPECT_EQ(ConvTy->getElementType()->getScalarSizeInBits(), 64U);
83
84 EltCnt = V8Int64Ty->getElementCount();
85 EXPECT_EQ(EltCnt.Min, 8U);
86 ASSERT_FALSE(EltCnt.Scalable);
87 }
88
89 TEST(VectorTypesTest, Scalable) {
90 LLVMContext Ctx;
91
92 Type *Int16Ty = Type::getInt16Ty(Ctx);
93 Type *Int32Ty = Type::getInt32Ty(Ctx);
94 Type *Int64Ty = Type::getInt64Ty(Ctx);
95 Type *Float64Ty = Type::getDoubleTy(Ctx);
96
97 VectorType *ScV8Int32Ty = VectorType::get(Int32Ty, 8, true);
98 ASSERT_TRUE(ScV8Int32Ty->isScalable());
99 EXPECT_EQ(ScV8Int32Ty->getNumElements(), 8U);
100 EXPECT_EQ(ScV8Int32Ty->getElementType()->getScalarSizeInBits(), 32U);
101
102 VectorType *ScV8Int16Ty = VectorType::get(Int16Ty, {8, true});
103 ASSERT_TRUE(ScV8Int16Ty->isScalable());
104 EXPECT_EQ(ScV8Int16Ty->getNumElements(), 8U);
105 EXPECT_EQ(ScV8Int16Ty->getElementType()->getScalarSizeInBits(), 16U);
106
107 ElementCount EltCnt(4, true);
108 VectorType *ScV4Int64Ty = VectorType::get(Int64Ty, EltCnt);
109 ASSERT_TRUE(ScV4Int64Ty->isScalable());
110 EXPECT_EQ(ScV4Int64Ty->getNumElements(), 4U);
111 EXPECT_EQ(ScV4Int64Ty->getElementType()->getScalarSizeInBits(), 64U);
112
113 VectorType *ScV2Int64Ty = VectorType::get(Int64Ty, EltCnt/2);
114 ASSERT_TRUE(ScV2Int64Ty->isScalable());
115 EXPECT_EQ(ScV2Int64Ty->getNumElements(), 2U);
116 EXPECT_EQ(ScV2Int64Ty->getElementType()->getScalarSizeInBits(), 64U);
117
118 VectorType *ScV8Int64Ty = VectorType::get(Int64Ty, EltCnt*2);
119 ASSERT_TRUE(ScV8Int64Ty->isScalable());
120 EXPECT_EQ(ScV8Int64Ty->getNumElements(), 8U);
121 EXPECT_EQ(ScV8Int64Ty->getElementType()->getScalarSizeInBits(), 64U);
122
123 VectorType *ScV4Float64Ty = VectorType::get(Float64Ty, EltCnt);
124 ASSERT_TRUE(ScV4Float64Ty->isScalable());
125 EXPECT_EQ(ScV4Float64Ty->getNumElements(), 4U);
126 EXPECT_EQ(ScV4Float64Ty->getElementType()->getScalarSizeInBits(), 64U);
127
128 VectorType *ExtTy = VectorType::getExtendedElementVectorType(ScV8Int16Ty);
129 EXPECT_EQ(ExtTy, ScV8Int32Ty);
130 ASSERT_TRUE(ExtTy->isScalable());
131 EXPECT_EQ(ExtTy->getNumElements(), 8U);
132 EXPECT_EQ(ExtTy->getElementType()->getScalarSizeInBits(), 32U);
133
134 VectorType *TruncTy = VectorType::getTruncatedElementVectorType(ScV8Int32Ty);
135 EXPECT_EQ(TruncTy, ScV8Int16Ty);
136 ASSERT_TRUE(TruncTy->isScalable());
137 EXPECT_EQ(TruncTy->getNumElements(), 8U);
138 EXPECT_EQ(TruncTy->getElementType()->getScalarSizeInBits(), 16U);
139
140 VectorType *HalvedTy = VectorType::getHalfElementsVectorType(ScV4Int64Ty);
141 EXPECT_EQ(HalvedTy, ScV2Int64Ty);
142 ASSERT_TRUE(HalvedTy->isScalable());
143 EXPECT_EQ(HalvedTy->getNumElements(), 2U);
144 EXPECT_EQ(HalvedTy->getElementType()->getScalarSizeInBits(), 64U);
145
146 VectorType *DoubledTy = VectorType::getDoubleElementsVectorType(ScV4Int64Ty);
147 EXPECT_EQ(DoubledTy, ScV8Int64Ty);
148 ASSERT_TRUE(DoubledTy->isScalable());
149 EXPECT_EQ(DoubledTy->getNumElements(), 8U);
150 EXPECT_EQ(DoubledTy->getElementType()->getScalarSizeInBits(), 64U);
151
152 VectorType *ConvTy = VectorType::getInteger(ScV4Float64Ty);
153 EXPECT_EQ(ConvTy, ScV4Int64Ty);
154 ASSERT_TRUE(ConvTy->isScalable());
155 EXPECT_EQ(ConvTy->getNumElements(), 4U);
156 EXPECT_EQ(ConvTy->getElementType()->getScalarSizeInBits(), 64U);
157
158 EltCnt = ScV8Int64Ty->getElementCount();
159 EXPECT_EQ(EltCnt.Min, 8U);
160 ASSERT_TRUE(EltCnt.Scalable);
161 }
162
163 } // end anonymous namespace