1 //===------- VectorTypeUtils.h - Vector type utility functions -*- C++ -*-====//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_IR_VECTORTYPEUTILS_H
10 #define LLVM_IR_VECTORTYPEUTILS_H
11
12 #include "llvm/IR/DerivedTypes.h"
13 #include "llvm/Support/Compiler.h"
14
15 namespace llvm {
16
17 /// A helper function for converting Scalar types to vector types. If
18 /// the incoming type is void, we return void. If the EC represents a
19 /// scalar, we return the scalar type.
toVectorTy(Type * Scalar,ElementCount EC)20 inline Type *toVectorTy(Type *Scalar, ElementCount EC) {
21 if (Scalar->isVoidTy() || Scalar->isMetadataTy() || EC.isScalar())
22 return Scalar;
23 return VectorType::get(Scalar, EC);
24 }
25
toVectorTy(Type * Scalar,unsigned VF)26 inline Type *toVectorTy(Type *Scalar, unsigned VF) {
27 return toVectorTy(Scalar, ElementCount::getFixed(VF));
28 }
29
30 /// A helper for converting structs of scalar types to structs of vector types.
31 /// Note:
32 /// - If \p EC is scalar, \p StructTy is returned unchanged
33 /// - Only unpacked literal struct types are supported
34 LLVM_ABI Type *toVectorizedStructTy(StructType *StructTy, ElementCount EC);
35
36 /// A helper for converting structs of vector types to structs of scalar types.
37 /// Note: Only unpacked literal struct types are supported.
38 LLVM_ABI Type *toScalarizedStructTy(StructType *StructTy);
39
40 /// Returns true if `StructTy` is an unpacked literal struct where all elements
41 /// are vectors of matching element count. This does not include empty structs.
42 LLVM_ABI bool isVectorizedStructTy(StructType *StructTy);
43
44 /// Returns true if `StructTy` is an unpacked literal struct where all elements
45 /// are scalars that can be used as vector element types.
46 LLVM_ABI bool canVectorizeStructTy(StructType *StructTy);
47
48 /// A helper for converting to vectorized types. For scalar types, this is
49 /// equivalent to calling `toVectorTy`. For struct types, this returns a new
50 /// struct where each element type has been widened to a vector type.
51 /// Note:
52 /// - If the incoming type is void, we return void
53 /// - If \p EC is scalar, \p Ty is returned unchanged
54 /// - Only unpacked literal struct types are supported
toVectorizedTy(Type * Ty,ElementCount EC)55 inline Type *toVectorizedTy(Type *Ty, ElementCount EC) {
56 if (StructType *StructTy = dyn_cast<StructType>(Ty))
57 return toVectorizedStructTy(StructTy, EC);
58 return toVectorTy(Ty, EC);
59 }
60
61 /// A helper for converting vectorized types to scalarized (non-vector) types.
62 /// For vector types, this is equivalent to calling .getScalarType(). For struct
63 /// types, this returns a new struct where each element type has been converted
64 /// to a scalar type. Note: Only unpacked literal struct types are supported.
toScalarizedTy(Type * Ty)65 inline Type *toScalarizedTy(Type *Ty) {
66 if (StructType *StructTy = dyn_cast<StructType>(Ty))
67 return toScalarizedStructTy(StructTy);
68 return Ty->getScalarType();
69 }
70
71 /// Returns true if `Ty` is a vector type or a struct of vector types where all
72 /// vector types share the same VF.
isVectorizedTy(Type * Ty)73 inline bool isVectorizedTy(Type *Ty) {
74 if (StructType *StructTy = dyn_cast<StructType>(Ty))
75 return isVectorizedStructTy(StructTy);
76 return Ty->isVectorTy();
77 }
78
79 /// Returns true if `Ty` is a valid vector element type, void, or an unpacked
80 /// literal struct where all elements are valid vector element types.
81 /// Note: Even if a type can be vectorized that does not mean it is valid to do
82 /// so in all cases. For example, a vectorized struct (as returned by
83 /// toVectorizedTy) does not perform (de)interleaving, so it can't be used for
84 /// vectorizing loads/stores.
canVectorizeTy(Type * Ty)85 inline bool canVectorizeTy(Type *Ty) {
86 if (StructType *StructTy = dyn_cast<StructType>(Ty))
87 return canVectorizeStructTy(StructTy);
88 return Ty->isVoidTy() || VectorType::isValidElementType(Ty);
89 }
90
91 /// Returns the types contained in `Ty`. For struct types, it returns the
92 /// elements, all other types are returned directly.
getContainedTypes(Type * const & Ty)93 inline ArrayRef<Type *> getContainedTypes(Type *const &Ty) {
94 if (auto *StructTy = dyn_cast<StructType>(Ty))
95 return StructTy->elements();
96 return ArrayRef<Type *>(&Ty, 1);
97 }
98
99 /// Returns the number of vector elements for a vectorized type.
getVectorizedTypeVF(Type * Ty)100 inline ElementCount getVectorizedTypeVF(Type *Ty) {
101 assert(isVectorizedTy(Ty) && "expected vectorized type");
102 return cast<VectorType>(getContainedTypes(Ty).front())->getElementCount();
103 }
104
isUnpackedStructLiteral(StructType * StructTy)105 inline bool isUnpackedStructLiteral(StructType *StructTy) {
106 return StructTy->isLiteral() && !StructTy->isPacked();
107 }
108
109 } // namespace llvm
110
111 #endif
112