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, 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, getScalarSizeInBits()); 30 return getVectorVT(Context, IntTy, 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, EltVT, getVectorElementCount()); 37 } 38 39 EVT EVT::getExtendedIntegerVT(LLVMContext &Context, unsigned BitWidth) { 40 EVT VT; 41 VT.LLVMTy = IntegerType::get(Context, 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(VT.getTypeForEVT(Context), NumElements, 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(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(16); 85 } 86 87 bool EVT::isExtended32BitVector() const { 88 return isExtendedVector() && 89 getExtendedSizeInBits() == TypeSize::getFixed(32); 90 } 91 92 bool EVT::isExtended64BitVector() const { 93 return isExtendedVector() && 94 getExtendedSizeInBits() == TypeSize::getFixed(64); 95 } 96 97 bool EVT::isExtended128BitVector() const { 98 return isExtendedVector() && 99 getExtendedSizeInBits() == TypeSize::getFixed(128); 100 } 101 102 bool EVT::isExtended256BitVector() const { 103 return isExtendedVector() && 104 getExtendedSizeInBits() == TypeSize::getFixed(256); 105 } 106 107 bool EVT::isExtended512BitVector() const { 108 return isExtendedVector() && 109 getExtendedSizeInBits() == TypeSize::getFixed(512); 110 } 111 112 bool EVT::isExtended1024BitVector() const { 113 return isExtendedVector() && 114 getExtendedSizeInBits() == TypeSize::getFixed(1024); 115 } 116 117 bool EVT::isExtended2048BitVector() const { 118 return isExtendedVector() && 119 getExtendedSizeInBits() == TypeSize::getFixed(2048); 120 } 121 122 bool EVT::isExtendedFixedLengthVector() const { 123 return isExtendedVector() && isa<FixedVectorType>(LLVMTy); 124 } 125 126 bool EVT::isExtendedScalableVector() const { 127 return isExtendedVector() && isa<ScalableVectorType>(LLVMTy); 128 } 129 130 EVT EVT::getExtendedVectorElementType() const { 131 assert(isExtended() && "Type is not extended!"); 132 return EVT::getEVT(cast<VectorType>(LLVMTy)->getElementType()); 133 } 134 135 unsigned EVT::getExtendedVectorNumElements() const { 136 assert(isExtended() && "Type is not extended!"); 137 ElementCount EC = cast<VectorType>(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>(LLVMTy)->getElementCount(); 150 } 151 152 TypeSize EVT::getExtendedSizeInBits() const { 153 assert(isExtended() && "Type is not extended!"); 154 if (IntegerType *ITy = dyn_cast<IntegerType>(LLVMTy)) 155 return TypeSize::getFixed(ITy->getBitWidth()); 156 if (VectorType *VTy = dyn_cast<VectorType>(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 (isVector()) 166 return (isScalableVector() ? "nxv" : "v") + 167 utostr(getVectorElementCount().getKnownMinValue()) + 168 getVectorElementType().getEVTString(); 169 if (isInteger()) 170 return "i" + utostr(getSizeInBits()); 171 if (isFloatingPoint()) 172 return "f" + utostr(getSizeInBits()); 173 llvm_unreachable("Invalid EVT!"); 174 case MVT::bf16: return "bf16"; 175 case MVT::ppcf128: return "ppcf128"; 176 case MVT::isVoid: return "isVoid"; 177 case MVT::Other: return "ch"; 178 case MVT::Glue: return "glue"; 179 case MVT::x86mmx: return "x86mmx"; 180 case MVT::x86amx: return "x86amx"; 181 case MVT::i64x8: return "i64x8"; 182 case MVT::Metadata: return "Metadata"; 183 case MVT::Untyped: return "Untyped"; 184 case MVT::funcref: return "funcref"; 185 case MVT::exnref: return "exnref"; 186 case MVT::externref: return "externref"; 187 case MVT::aarch64svcount: 188 return "aarch64svcount"; 189 case MVT::spirvbuiltin: 190 return "spirvbuiltin"; 191 } 192 } 193 194 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 195 void EVT::dump() const { 196 print(dbgs()); 197 dbgs() << "\n"; 198 } 199 #endif 200 201 /// getTypeForEVT - This method returns an LLVM type corresponding to the 202 /// specified EVT. For integer types, this returns an unsigned type. Note 203 /// that this will abort for types that cannot be represented. 204 Type *EVT::getTypeForEVT(LLVMContext &Context) const { 205 // clang-format off 206 switch (V.SimpleTy) { 207 default: 208 assert(isExtended() && "Type is not extended!"); 209 return LLVMTy; 210 case MVT::isVoid: return Type::getVoidTy(Context); 211 case MVT::x86mmx: return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1); 212 case MVT::aarch64svcount: 213 return TargetExtType::get(Context, "aarch64.svcount"); 214 case MVT::x86amx: return Type::getX86_AMXTy(Context); 215 case MVT::i64x8: return IntegerType::get(Context, 512); 216 case MVT::externref: return Type::getWasm_ExternrefTy(Context); 217 case MVT::funcref: return Type::getWasm_FuncrefTy(Context); 218 case MVT::Metadata: return Type::getMetadataTy(Context); 219 #define GET_VT_EVT(Ty, EVT) case MVT::Ty: return EVT; 220 #include "llvm/CodeGen/GenVT.inc" 221 #undef GET_VT_EVT 222 } 223 // clang-format on 224 } 225 226 /// Return the value type corresponding to the specified type. 227 /// If HandleUnknown is true, unknown types are returned as Other, otherwise 228 /// they are invalid. 229 /// NB: This includes pointer types, which require a DataLayout to convert 230 /// to a concrete value type. 231 MVT MVT::getVT(Type *Ty, bool HandleUnknown){ 232 assert(Ty != nullptr && "Invalid type"); 233 switch (Ty->getTypeID()) { 234 default: 235 if (HandleUnknown) return MVT(MVT::Other); 236 llvm_unreachable("Unknown type!"); 237 case Type::VoidTyID: 238 return MVT::isVoid; 239 case Type::IntegerTyID: 240 return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth()); 241 case Type::HalfTyID: return MVT(MVT::f16); 242 case Type::BFloatTyID: return MVT(MVT::bf16); 243 case Type::FloatTyID: return MVT(MVT::f32); 244 case Type::DoubleTyID: return MVT(MVT::f64); 245 case Type::X86_FP80TyID: 246 return MVT(MVT::f80); 247 case Type::TargetExtTyID: { 248 TargetExtType *TargetExtTy = cast<TargetExtType>(Ty); 249 if (TargetExtTy->getName() == "aarch64.svcount") 250 return MVT(MVT::aarch64svcount); 251 else if (TargetExtTy->getName().starts_with("spirv.")) 252 return MVT(MVT::spirvbuiltin); 253 if (HandleUnknown) 254 return MVT(MVT::Other); 255 llvm_unreachable("Unknown target ext type!"); 256 } 257 case Type::X86_AMXTyID: return MVT(MVT::x86amx); 258 case Type::FP128TyID: return MVT(MVT::f128); 259 case Type::PPC_FP128TyID: return MVT(MVT::ppcf128); 260 case Type::FixedVectorTyID: 261 case Type::ScalableVectorTyID: { 262 VectorType *VTy = cast<VectorType>(Ty); 263 return getVectorVT( 264 getVT(VTy->getElementType(), /*HandleUnknown=*/ false), 265 VTy->getElementCount()); 266 } 267 } 268 } 269 270 /// getEVT - Return the value type corresponding to the specified type. 271 /// If HandleUnknown is true, unknown types are returned as Other, otherwise 272 /// they are invalid. 273 /// NB: This includes pointer types, which require a DataLayout to convert 274 /// to a concrete value type. 275 EVT EVT::getEVT(Type *Ty, bool HandleUnknown){ 276 switch (Ty->getTypeID()) { 277 default: 278 return MVT::getVT(Ty, HandleUnknown); 279 case Type::TokenTyID: 280 return MVT::Untyped; 281 case Type::IntegerTyID: 282 return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth()); 283 case Type::FixedVectorTyID: 284 case Type::ScalableVectorTyID: { 285 VectorType *VTy = cast<VectorType>(Ty); 286 return getVectorVT(Ty->getContext(), 287 getEVT(VTy->getElementType(), /*HandleUnknown=*/ false), 288 VTy->getElementCount()); 289 } 290 } 291 } 292 293 const fltSemantics &MVT::getFltSemantics() const { 294 switch (getScalarType().SimpleTy) { 295 default: llvm_unreachable("Unknown FP format"); 296 case MVT::f16: return APFloat::IEEEhalf(); 297 case MVT::bf16: return APFloat::BFloat(); 298 case MVT::f32: return APFloat::IEEEsingle(); 299 case MVT::f64: return APFloat::IEEEdouble(); 300 case MVT::f80: return APFloat::x87DoubleExtended(); 301 case MVT::f128: return APFloat::IEEEquad(); 302 case MVT::ppcf128: return APFloat::PPCDoubleDouble(); 303 } 304 } 305 306 const fltSemantics &EVT::getFltSemantics() const { 307 return getScalarType().getSimpleVT().getFltSemantics(); 308 } 309 310 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 311 void MVT::dump() const { 312 print(dbgs()); 313 dbgs() << "\n"; 314 } 315 #endif 316 317 void MVT::print(raw_ostream &OS) const { 318 if (SimpleTy == INVALID_SIMPLE_VALUE_TYPE) 319 OS << "invalid"; 320 else 321 OS << EVT(*this).getEVTString(); 322 } 323