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 (isRISCVVectorTuple()) { 166 unsigned Sz = getSizeInBits().getKnownMinValue(); 167 unsigned NF = getRISCVVectorTupleNumFields(); 168 unsigned MinNumElts = Sz / (NF * 8); 169 return "riscv_nxv" + utostr(MinNumElts) + "i8x" + utostr(NF); 170 } 171 if (isVector()) 172 return (isScalableVector() ? "nxv" : "v") + 173 utostr(getVectorElementCount().getKnownMinValue()) + 174 getVectorElementType().getEVTString(); 175 if (isInteger()) 176 return "i" + utostr(getSizeInBits()); 177 if (isFloatingPoint()) 178 return "f" + utostr(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 } 198 } 199 200 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 201 void EVT::dump() const { 202 print(dbgs()); 203 dbgs() << "\n"; 204 } 205 #endif 206 207 /// getTypeForEVT - This method returns an LLVM type corresponding to the 208 /// specified EVT. For integer types, this returns an unsigned type. Note 209 /// that this will abort for types that cannot be represented. 210 Type *EVT::getTypeForEVT(LLVMContext &Context) const { 211 // clang-format off 212 switch (V.SimpleTy) { 213 default: 214 assert(isExtended() && "Type is not extended!"); 215 return LLVMTy; 216 case MVT::isVoid: return Type::getVoidTy(Context); 217 case MVT::x86mmx: return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1); 218 case MVT::aarch64svcount: 219 return TargetExtType::get(Context, "aarch64.svcount"); 220 case MVT::x86amx: return Type::getX86_AMXTy(Context); 221 case MVT::i64x8: return IntegerType::get(Context, 512); 222 case MVT::externref: return Type::getWasm_ExternrefTy(Context); 223 case MVT::funcref: return Type::getWasm_FuncrefTy(Context); 224 case MVT::Metadata: return Type::getMetadataTy(Context); 225 #define GET_VT_EVT(Ty, EVT) case MVT::Ty: return EVT; 226 #include "llvm/CodeGen/GenVT.inc" 227 #undef GET_VT_EVT 228 } 229 // clang-format on 230 } 231 232 /// Return the value type corresponding to the specified type. 233 /// If HandleUnknown is true, unknown types are returned as Other, otherwise 234 /// they are invalid. 235 /// NB: This includes pointer types, which require a DataLayout to convert 236 /// to a concrete value type. 237 MVT MVT::getVT(Type *Ty, bool HandleUnknown){ 238 assert(Ty != nullptr && "Invalid type"); 239 switch (Ty->getTypeID()) { 240 default: 241 if (HandleUnknown) return MVT(MVT::Other); 242 llvm_unreachable("Unknown type!"); 243 case Type::VoidTyID: 244 return MVT::isVoid; 245 case Type::IntegerTyID: 246 return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth()); 247 case Type::HalfTyID: return MVT(MVT::f16); 248 case Type::BFloatTyID: return MVT(MVT::bf16); 249 case Type::FloatTyID: return MVT(MVT::f32); 250 case Type::DoubleTyID: return MVT(MVT::f64); 251 case Type::X86_FP80TyID: 252 return MVT(MVT::f80); 253 case Type::TargetExtTyID: { 254 TargetExtType *TargetExtTy = cast<TargetExtType>(Ty); 255 if (TargetExtTy->getName() == "aarch64.svcount") 256 return MVT(MVT::aarch64svcount); 257 else if (TargetExtTy->getName().starts_with("spirv.")) 258 return MVT(MVT::spirvbuiltin); 259 if (TargetExtTy->getName() == "riscv.vector.tuple") { 260 unsigned Sz = cast<ScalableVectorType>(TargetExtTy->getTypeParameter(0)) 261 ->getMinNumElements() * 262 8; 263 unsigned NF = TargetExtTy->getIntParameter(0); 264 265 return MVT::getRISCVVectorTupleVT(Sz * NF, NF); 266 } 267 if (HandleUnknown) 268 return MVT(MVT::Other); 269 llvm_unreachable("Unknown target ext type!"); 270 } 271 case Type::X86_AMXTyID: return MVT(MVT::x86amx); 272 case Type::FP128TyID: return MVT(MVT::f128); 273 case Type::PPC_FP128TyID: return MVT(MVT::ppcf128); 274 case Type::FixedVectorTyID: 275 case Type::ScalableVectorTyID: { 276 VectorType *VTy = cast<VectorType>(Ty); 277 return getVectorVT( 278 getVT(VTy->getElementType(), /*HandleUnknown=*/ false), 279 VTy->getElementCount()); 280 } 281 } 282 } 283 284 /// getEVT - Return the value type corresponding to the specified type. 285 /// If HandleUnknown is true, unknown types are returned as Other, otherwise 286 /// they are invalid. 287 /// NB: This includes pointer types, which require a DataLayout to convert 288 /// to a concrete value type. 289 EVT EVT::getEVT(Type *Ty, bool HandleUnknown){ 290 switch (Ty->getTypeID()) { 291 default: 292 return MVT::getVT(Ty, HandleUnknown); 293 case Type::TokenTyID: 294 return MVT::Untyped; 295 case Type::IntegerTyID: 296 return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth()); 297 case Type::FixedVectorTyID: 298 case Type::ScalableVectorTyID: { 299 VectorType *VTy = cast<VectorType>(Ty); 300 return getVectorVT(Ty->getContext(), 301 getEVT(VTy->getElementType(), /*HandleUnknown=*/ false), 302 VTy->getElementCount()); 303 } 304 } 305 } 306 307 const fltSemantics &MVT::getFltSemantics() const { 308 switch (getScalarType().SimpleTy) { 309 default: llvm_unreachable("Unknown FP format"); 310 case MVT::f16: return APFloat::IEEEhalf(); 311 case MVT::bf16: return APFloat::BFloat(); 312 case MVT::f32: return APFloat::IEEEsingle(); 313 case MVT::f64: return APFloat::IEEEdouble(); 314 case MVT::f80: return APFloat::x87DoubleExtended(); 315 case MVT::f128: return APFloat::IEEEquad(); 316 case MVT::ppcf128: return APFloat::PPCDoubleDouble(); 317 } 318 } 319 320 const fltSemantics &EVT::getFltSemantics() const { 321 return getScalarType().getSimpleVT().getFltSemantics(); 322 } 323 324 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 325 void MVT::dump() const { 326 print(dbgs()); 327 dbgs() << "\n"; 328 } 329 #endif 330 331 void MVT::print(raw_ostream &OS) const { 332 if (SimpleTy == INVALID_SIMPLE_VALUE_TYPE) 333 OS << "invalid"; 334 else 335 OS << EVT(*this).getEVTString(); 336 } 337