1 | //===----------- ValueTypes.cpp - Implementation of EVT methods -----------===// |
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 | #include "llvm/CodeGen/ValueTypes.h" |
10 | #include "llvm/ADT/APFloat.h" |
11 | #include "llvm/ADT/StringExtras.h" |
12 | #include "llvm/IR/DerivedTypes.h" |
13 | #include "llvm/IR/Type.h" |
14 | #include "llvm/Support/Debug.h" |
15 | #include "llvm/Support/ErrorHandling.h" |
16 | #include "llvm/Support/TypeSize.h" |
17 | #include "llvm/Support/WithColor.h" |
18 | using namespace llvm; |
19 | |
20 | EVT EVT::changeExtendedTypeToInteger() const { |
21 | assert(isExtended() && "Type is not extended!" ); |
22 | LLVMContext &Context = LLVMTy->getContext(); |
23 | return getIntegerVT(Context, BitWidth: getSizeInBits()); |
24 | } |
25 | |
26 | EVT EVT::changeExtendedVectorElementTypeToInteger() const { |
27 | assert(isExtended() && "Type is not extended!" ); |
28 | LLVMContext &Context = LLVMTy->getContext(); |
29 | EVT IntTy = getIntegerVT(Context, BitWidth: getScalarSizeInBits()); |
30 | return getVectorVT(Context, VT: IntTy, EC: getVectorElementCount()); |
31 | } |
32 | |
33 | EVT EVT::changeExtendedVectorElementType(EVT EltVT) const { |
34 | assert(isExtended() && "Type is not extended!" ); |
35 | LLVMContext &Context = LLVMTy->getContext(); |
36 | return getVectorVT(Context, VT: EltVT, EC: getVectorElementCount()); |
37 | } |
38 | |
39 | EVT EVT::getExtendedIntegerVT(LLVMContext &Context, unsigned BitWidth) { |
40 | EVT VT; |
41 | VT.LLVMTy = IntegerType::get(C&: Context, NumBits: BitWidth); |
42 | assert(VT.isExtended() && "Type is not extended!" ); |
43 | return VT; |
44 | } |
45 | |
46 | EVT EVT::getExtendedVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, |
47 | bool IsScalable) { |
48 | EVT ResultVT; |
49 | ResultVT.LLVMTy = |
50 | VectorType::get(ElementType: VT.getTypeForEVT(Context), NumElements, Scalable: IsScalable); |
51 | assert(ResultVT.isExtended() && "Type is not extended!" ); |
52 | return ResultVT; |
53 | } |
54 | |
55 | EVT EVT::getExtendedVectorVT(LLVMContext &Context, EVT VT, ElementCount EC) { |
56 | EVT ResultVT; |
57 | ResultVT.LLVMTy = VectorType::get(ElementType: VT.getTypeForEVT(Context), EC); |
58 | assert(ResultVT.isExtended() && "Type is not extended!" ); |
59 | return ResultVT; |
60 | } |
61 | |
62 | bool EVT::isExtendedFloatingPoint() const { |
63 | assert(isExtended() && "Type is not extended!" ); |
64 | return LLVMTy->isFPOrFPVectorTy(); |
65 | } |
66 | |
67 | bool EVT::isExtendedInteger() const { |
68 | assert(isExtended() && "Type is not extended!" ); |
69 | return LLVMTy->isIntOrIntVectorTy(); |
70 | } |
71 | |
72 | bool EVT::isExtendedScalarInteger() const { |
73 | assert(isExtended() && "Type is not extended!" ); |
74 | return LLVMTy->isIntegerTy(); |
75 | } |
76 | |
77 | bool EVT::isExtendedVector() const { |
78 | assert(isExtended() && "Type is not extended!" ); |
79 | return LLVMTy->isVectorTy(); |
80 | } |
81 | |
82 | bool EVT::isExtended16BitVector() const { |
83 | return isExtendedVector() && |
84 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 16); |
85 | } |
86 | |
87 | bool EVT::isExtended32BitVector() const { |
88 | return isExtendedVector() && |
89 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 32); |
90 | } |
91 | |
92 | bool EVT::isExtended64BitVector() const { |
93 | return isExtendedVector() && |
94 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 64); |
95 | } |
96 | |
97 | bool EVT::isExtended128BitVector() const { |
98 | return isExtendedVector() && |
99 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 128); |
100 | } |
101 | |
102 | bool EVT::isExtended256BitVector() const { |
103 | return isExtendedVector() && |
104 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 256); |
105 | } |
106 | |
107 | bool EVT::isExtended512BitVector() const { |
108 | return isExtendedVector() && |
109 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 512); |
110 | } |
111 | |
112 | bool EVT::isExtended1024BitVector() const { |
113 | return isExtendedVector() && |
114 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 1024); |
115 | } |
116 | |
117 | bool EVT::isExtended2048BitVector() const { |
118 | return isExtendedVector() && |
119 | getExtendedSizeInBits() == TypeSize::getFixed(ExactSize: 2048); |
120 | } |
121 | |
122 | bool EVT::isExtendedFixedLengthVector() const { |
123 | return isExtendedVector() && isa<FixedVectorType>(Val: LLVMTy); |
124 | } |
125 | |
126 | bool EVT::isExtendedScalableVector() const { |
127 | return isExtendedVector() && isa<ScalableVectorType>(Val: LLVMTy); |
128 | } |
129 | |
130 | EVT EVT::getExtendedVectorElementType() const { |
131 | assert(isExtended() && "Type is not extended!" ); |
132 | return EVT::getEVT(Ty: cast<VectorType>(Val: LLVMTy)->getElementType()); |
133 | } |
134 | |
135 | unsigned EVT::getExtendedVectorNumElements() const { |
136 | assert(isExtended() && "Type is not extended!" ); |
137 | ElementCount EC = cast<VectorType>(Val: LLVMTy)->getElementCount(); |
138 | if (EC.isScalable()) { |
139 | WithColor::warning() |
140 | << "The code that requested the fixed number of elements has made the " |
141 | "assumption that this vector is not scalable. This assumption was " |
142 | "not correct, and this may lead to broken code\n" ; |
143 | } |
144 | return EC.getKnownMinValue(); |
145 | } |
146 | |
147 | ElementCount EVT::getExtendedVectorElementCount() const { |
148 | assert(isExtended() && "Type is not extended!" ); |
149 | return cast<VectorType>(Val: LLVMTy)->getElementCount(); |
150 | } |
151 | |
152 | TypeSize EVT::getExtendedSizeInBits() const { |
153 | assert(isExtended() && "Type is not extended!" ); |
154 | if (IntegerType *ITy = dyn_cast<IntegerType>(Val: LLVMTy)) |
155 | return TypeSize::getFixed(ExactSize: ITy->getBitWidth()); |
156 | if (VectorType *VTy = dyn_cast<VectorType>(Val: LLVMTy)) |
157 | return VTy->getPrimitiveSizeInBits(); |
158 | llvm_unreachable("Unrecognized extended type!" ); |
159 | } |
160 | |
161 | /// getEVTString - This function returns value type as a string, e.g. "i32". |
162 | std::string EVT::getEVTString() const { |
163 | switch (V.SimpleTy) { |
164 | default: |
165 | if (isRISCVVectorTuple()) { |
166 | unsigned Sz = getSizeInBits().getKnownMinValue(); |
167 | unsigned NF = getRISCVVectorTupleNumFields(); |
168 | unsigned MinNumElts = Sz / (NF * 8); |
169 | return "riscv_nxv" + utostr(X: MinNumElts) + "i8x" + utostr(X: NF); |
170 | } |
171 | if (isVector()) |
172 | return (isScalableVector() ? "nxv" : "v" ) + |
173 | utostr(X: getVectorElementCount().getKnownMinValue()) + |
174 | getVectorElementType().getEVTString(); |
175 | if (isInteger()) |
176 | return "i" + utostr(X: getSizeInBits()); |
177 | if (isFloatingPoint()) |
178 | return "f" + utostr(X: getSizeInBits()); |
179 | llvm_unreachable("Invalid EVT!" ); |
180 | case MVT::bf16: return "bf16" ; |
181 | case MVT::ppcf128: return "ppcf128" ; |
182 | case MVT::isVoid: return "isVoid" ; |
183 | case MVT::Other: return "ch" ; |
184 | case MVT::Glue: return "glue" ; |
185 | case MVT::x86mmx: return "x86mmx" ; |
186 | case MVT::x86amx: return "x86amx" ; |
187 | case MVT::i64x8: return "i64x8" ; |
188 | case MVT::Metadata: return "Metadata" ; |
189 | case MVT::Untyped: return "Untyped" ; |
190 | case MVT::funcref: return "funcref" ; |
191 | case MVT::exnref: return "exnref" ; |
192 | case MVT::externref: return "externref" ; |
193 | case MVT::aarch64svcount: |
194 | return "aarch64svcount" ; |
195 | case MVT::spirvbuiltin: |
196 | return "spirvbuiltin" ; |
197 | case MVT::amdgpuBufferFatPointer: |
198 | return "amdgpuBufferFatPointer" ; |
199 | case MVT::amdgpuBufferStridedPointer: |
200 | return "amdgpuBufferStridedPointer" ; |
201 | case MVT::aarch64mfp8: |
202 | return "aarch64mfp8" ; |
203 | } |
204 | } |
205 | |
206 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
207 | void EVT::dump() const { |
208 | print(dbgs()); |
209 | dbgs() << "\n" ; |
210 | } |
211 | #endif |
212 | |
213 | /// getTypeForEVT - This method returns an LLVM type corresponding to the |
214 | /// specified EVT. For integer types, this returns an unsigned type. Note |
215 | /// that this will abort for types that cannot be represented. |
216 | Type *EVT::getTypeForEVT(LLVMContext &Context) const { |
217 | // clang-format off |
218 | switch (V.SimpleTy) { |
219 | default: |
220 | assert(isExtended() && "Type is not extended!" ); |
221 | return LLVMTy; |
222 | case MVT::isVoid: return Type::getVoidTy(C&: Context); |
223 | case MVT::x86mmx: return llvm::FixedVectorType::get(ElementType: llvm::IntegerType::get(C&: Context, NumBits: 64), NumElts: 1); |
224 | case MVT::aarch64svcount: |
225 | return TargetExtType::get(Context, Name: "aarch64.svcount" ); |
226 | case MVT::aarch64mfp8: |
227 | return FixedVectorType::get(ElementType: IntegerType::get(C&: Context, NumBits: 8), NumElts: 1); |
228 | case MVT::x86amx: return Type::getX86_AMXTy(C&: Context); |
229 | case MVT::i64x8: return IntegerType::get(C&: Context, NumBits: 512); |
230 | case MVT::amdgpuBufferFatPointer: return IntegerType::get(C&: Context, NumBits: 160); |
231 | case MVT::amdgpuBufferStridedPointer: return IntegerType::get(C&: Context, NumBits: 192); |
232 | case MVT::externref: return Type::getWasm_ExternrefTy(C&: Context); |
233 | case MVT::funcref: return Type::getWasm_FuncrefTy(C&: Context); |
234 | case MVT::Metadata: return Type::getMetadataTy(C&: Context); |
235 | #define GET_VT_EVT(Ty, EVT) case MVT::Ty: return EVT; |
236 | #include "llvm/CodeGen/GenVT.inc" |
237 | #undef GET_VT_EVT |
238 | } |
239 | // clang-format on |
240 | } |
241 | |
242 | /// Return the value type corresponding to the specified type. |
243 | /// If HandleUnknown is true, unknown types are returned as Other, otherwise |
244 | /// they are invalid. |
245 | /// NB: This includes pointer types, which require a DataLayout to convert |
246 | /// to a concrete value type. |
247 | MVT MVT::getVT(Type *Ty, bool HandleUnknown){ |
248 | assert(Ty != nullptr && "Invalid type" ); |
249 | switch (Ty->getTypeID()) { |
250 | default: |
251 | if (HandleUnknown) return MVT(MVT::Other); |
252 | llvm_unreachable("Unknown type!" ); |
253 | case Type::VoidTyID: |
254 | return MVT::isVoid; |
255 | case Type::IntegerTyID: |
256 | return getIntegerVT(BitWidth: cast<IntegerType>(Val: Ty)->getBitWidth()); |
257 | case Type::HalfTyID: return MVT(MVT::f16); |
258 | case Type::BFloatTyID: return MVT(MVT::bf16); |
259 | case Type::FloatTyID: return MVT(MVT::f32); |
260 | case Type::DoubleTyID: return MVT(MVT::f64); |
261 | case Type::X86_FP80TyID: |
262 | return MVT(MVT::f80); |
263 | case Type::TargetExtTyID: { |
264 | TargetExtType *TargetExtTy = cast<TargetExtType>(Val: Ty); |
265 | if (TargetExtTy->getName() == "aarch64.svcount" ) |
266 | return MVT(MVT::aarch64svcount); |
267 | else if (TargetExtTy->getName().starts_with(Prefix: "spirv." )) |
268 | return MVT(MVT::spirvbuiltin); |
269 | if (TargetExtTy->getName() == "riscv.vector.tuple" ) { |
270 | unsigned Sz = cast<ScalableVectorType>(Val: TargetExtTy->getTypeParameter(i: 0)) |
271 | ->getMinNumElements() * |
272 | 8; |
273 | unsigned NF = TargetExtTy->getIntParameter(i: 0); |
274 | |
275 | return MVT::getRISCVVectorTupleVT(Sz: Sz * NF, NFields: NF); |
276 | } |
277 | if (HandleUnknown) |
278 | return MVT(MVT::Other); |
279 | llvm_unreachable("Unknown target ext type!" ); |
280 | } |
281 | case Type::X86_AMXTyID: return MVT(MVT::x86amx); |
282 | case Type::FP128TyID: return MVT(MVT::f128); |
283 | case Type::PPC_FP128TyID: return MVT(MVT::ppcf128); |
284 | case Type::FixedVectorTyID: |
285 | case Type::ScalableVectorTyID: { |
286 | VectorType *VTy = cast<VectorType>(Val: Ty); |
287 | return getVectorVT( |
288 | VT: getVT(Ty: VTy->getElementType(), /*HandleUnknown=*/ false), |
289 | EC: VTy->getElementCount()); |
290 | } |
291 | } |
292 | } |
293 | |
294 | /// getEVT - Return the value type corresponding to the specified type. |
295 | /// If HandleUnknown is true, unknown types are returned as Other, otherwise |
296 | /// they are invalid. |
297 | /// NB: This includes pointer types, which require a DataLayout to convert |
298 | /// to a concrete value type. |
299 | EVT EVT::getEVT(Type *Ty, bool HandleUnknown){ |
300 | switch (Ty->getTypeID()) { |
301 | default: |
302 | return MVT::getVT(Ty, HandleUnknown); |
303 | case Type::TokenTyID: |
304 | return MVT::Untyped; |
305 | case Type::IntegerTyID: |
306 | return getIntegerVT(Context&: Ty->getContext(), BitWidth: cast<IntegerType>(Val: Ty)->getBitWidth()); |
307 | case Type::FixedVectorTyID: |
308 | case Type::ScalableVectorTyID: { |
309 | VectorType *VTy = cast<VectorType>(Val: Ty); |
310 | return getVectorVT(Context&: Ty->getContext(), |
311 | VT: getEVT(Ty: VTy->getElementType(), /*HandleUnknown=*/ false), |
312 | EC: VTy->getElementCount()); |
313 | } |
314 | } |
315 | } |
316 | |
317 | const fltSemantics &MVT::getFltSemantics() const { |
318 | switch (getScalarType().SimpleTy) { |
319 | default: llvm_unreachable("Unknown FP format" ); |
320 | case MVT::f16: return APFloat::IEEEhalf(); |
321 | case MVT::bf16: return APFloat::BFloat(); |
322 | case MVT::f32: return APFloat::IEEEsingle(); |
323 | case MVT::f64: return APFloat::IEEEdouble(); |
324 | case MVT::f80: return APFloat::x87DoubleExtended(); |
325 | case MVT::f128: return APFloat::IEEEquad(); |
326 | case MVT::ppcf128: return APFloat::PPCDoubleDouble(); |
327 | } |
328 | } |
329 | |
330 | const fltSemantics &EVT::getFltSemantics() const { |
331 | return getScalarType().getSimpleVT().getFltSemantics(); |
332 | } |
333 | |
334 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
335 | void MVT::dump() const { |
336 | print(dbgs()); |
337 | dbgs() << "\n" ; |
338 | } |
339 | #endif |
340 | |
341 | void MVT::print(raw_ostream &OS) const { |
342 | if (SimpleTy == INVALID_SIMPLE_VALUE_TYPE) |
343 | OS << "invalid" ; |
344 | else |
345 | OS << EVT(*this).getEVTString(); |
346 | } |
347 | |