349 lines · cpp
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-exception6//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"18using namespace llvm;19 20EVT EVT::changeExtendedTypeToInteger() const {21 assert(isExtended() && "Type is not extended!");22 LLVMContext &Context = LLVMTy->getContext();23 return getIntegerVT(Context, getSizeInBits());24}25 26EVT 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 33EVT 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 39EVT 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 46EVT 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 55EVT 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 62bool EVT::isExtendedFloatingPoint() const {63 assert(isExtended() && "Type is not extended!");64 return LLVMTy->isFPOrFPVectorTy();65}66 67bool EVT::isExtendedInteger() const {68 assert(isExtended() && "Type is not extended!");69 return LLVMTy->isIntOrIntVectorTy();70}71 72bool EVT::isExtendedScalarInteger() const {73 assert(isExtended() && "Type is not extended!");74 return LLVMTy->isIntegerTy();75}76 77bool EVT::isExtendedVector() const {78 assert(isExtended() && "Type is not extended!");79 return LLVMTy->isVectorTy();80}81 82bool EVT::isExtended16BitVector() const {83 return isExtendedVector() &&84 getExtendedSizeInBits() == TypeSize::getFixed(16);85}86 87bool EVT::isExtended32BitVector() const {88 return isExtendedVector() &&89 getExtendedSizeInBits() == TypeSize::getFixed(32);90}91 92bool EVT::isExtended64BitVector() const {93 return isExtendedVector() &&94 getExtendedSizeInBits() == TypeSize::getFixed(64);95}96 97bool EVT::isExtended128BitVector() const {98 return isExtendedVector() &&99 getExtendedSizeInBits() == TypeSize::getFixed(128);100}101 102bool EVT::isExtended256BitVector() const {103 return isExtendedVector() &&104 getExtendedSizeInBits() == TypeSize::getFixed(256);105}106 107bool EVT::isExtended512BitVector() const {108 return isExtendedVector() &&109 getExtendedSizeInBits() == TypeSize::getFixed(512);110}111 112bool EVT::isExtended1024BitVector() const {113 return isExtendedVector() &&114 getExtendedSizeInBits() == TypeSize::getFixed(1024);115}116 117bool EVT::isExtended2048BitVector() const {118 return isExtendedVector() &&119 getExtendedSizeInBits() == TypeSize::getFixed(2048);120}121 122bool EVT::isExtendedFixedLengthVector() const {123 return isExtendedVector() && isa<FixedVectorType>(LLVMTy);124}125 126bool EVT::isExtendedScalableVector() const {127 return isExtendedVector() && isa<ScalableVectorType>(LLVMTy);128}129 130EVT EVT::getExtendedVectorElementType() const {131 assert(isExtended() && "Type is not extended!");132 return EVT::getEVT(cast<VectorType>(LLVMTy)->getElementType());133}134 135unsigned 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 147ElementCount EVT::getExtendedVectorElementCount() const {148 assert(isExtended() && "Type is not extended!");149 return cast<VectorType>(LLVMTy)->getElementCount();150}151 152TypeSize 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".162std::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 if (isCheriCapability())180 return "c" + utostr(getSizeInBits());181 llvm_unreachable("Invalid EVT!");182 case MVT::bf16: return "bf16";183 case MVT::ppcf128: return "ppcf128";184 case MVT::isVoid: return "isVoid";185 case MVT::Other: return "ch";186 case MVT::Glue: return "glue";187 case MVT::x86mmx: return "x86mmx";188 case MVT::x86amx: return "x86amx";189 case MVT::i64x8: return "i64x8";190 case MVT::Metadata: return "Metadata";191 case MVT::Untyped: return "Untyped";192 case MVT::funcref: return "funcref";193 case MVT::exnref: return "exnref";194 case MVT::externref: return "externref";195 case MVT::aarch64svcount:196 return "aarch64svcount";197 case MVT::spirvbuiltin:198 return "spirvbuiltin";199 case MVT::amdgpuBufferFatPointer:200 return "amdgpuBufferFatPointer";201 case MVT::amdgpuBufferStridedPointer:202 return "amdgpuBufferStridedPointer";203 case MVT::aarch64mfp8:204 return "aarch64mfp8";205 }206}207 208#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)209void EVT::dump() const {210 print(dbgs());211 dbgs() << "\n";212}213#endif214 215/// getTypeForEVT - This method returns an LLVM type corresponding to the216/// specified EVT. For integer types, this returns an unsigned type. Note217/// that this will abort for types that cannot be represented.218Type *EVT::getTypeForEVT(LLVMContext &Context) const {219 // clang-format off220 switch (V.SimpleTy) {221 default:222 assert(isExtended() && "Type is not extended!");223 return LLVMTy;224 case MVT::isVoid: return Type::getVoidTy(Context);225 case MVT::x86mmx: return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1);226 case MVT::aarch64svcount:227 return TargetExtType::get(Context, "aarch64.svcount");228 case MVT::aarch64mfp8:229 return FixedVectorType::get(IntegerType::get(Context, 8), 1);230 case MVT::x86amx: return Type::getX86_AMXTy(Context);231 case MVT::i64x8: return IntegerType::get(Context, 512);232 case MVT::amdgpuBufferFatPointer: return IntegerType::get(Context, 160);233 case MVT::amdgpuBufferStridedPointer: return IntegerType::get(Context, 192);234 case MVT::externref: return Type::getWasm_ExternrefTy(Context);235 case MVT::funcref: return Type::getWasm_FuncrefTy(Context);236 case MVT::Metadata: return Type::getMetadataTy(Context);237#define GET_VT_EVT(Ty, EVT) case MVT::Ty: return EVT;238#include "llvm/CodeGen/GenVT.inc"239#undef GET_VT_EVT240 }241 // clang-format on242}243 244/// Return the value type corresponding to the specified type.245/// If HandleUnknown is true, unknown types are returned as Other, otherwise246/// they are invalid.247/// NB: This includes pointer types, which require a DataLayout to convert248/// to a concrete value type.249MVT MVT::getVT(Type *Ty, bool HandleUnknown){250 assert(Ty != nullptr && "Invalid type");251 switch (Ty->getTypeID()) {252 default:253 if (HandleUnknown) return MVT(MVT::Other);254 llvm_unreachable("Unknown type!");255 case Type::VoidTyID:256 return MVT::isVoid;257 case Type::IntegerTyID:258 return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth());259 case Type::HalfTyID: return MVT(MVT::f16);260 case Type::BFloatTyID: return MVT(MVT::bf16);261 case Type::FloatTyID: return MVT(MVT::f32);262 case Type::DoubleTyID: return MVT(MVT::f64);263 case Type::X86_FP80TyID:264 return MVT(MVT::f80);265 case Type::TargetExtTyID: {266 TargetExtType *TargetExtTy = cast<TargetExtType>(Ty);267 if (TargetExtTy->getName() == "aarch64.svcount")268 return MVT(MVT::aarch64svcount);269 else if (TargetExtTy->getName().starts_with("spirv."))270 return MVT(MVT::spirvbuiltin);271 if (TargetExtTy->getName() == "riscv.vector.tuple") {272 unsigned Sz = cast<ScalableVectorType>(TargetExtTy->getTypeParameter(0))273 ->getMinNumElements() *274 8;275 unsigned NF = TargetExtTy->getIntParameter(0);276 277 return MVT::getRISCVVectorTupleVT(Sz * NF, NF);278 }279 if (HandleUnknown)280 return MVT(MVT::Other);281 llvm_unreachable("Unknown target ext type!");282 }283 case Type::X86_AMXTyID: return MVT(MVT::x86amx);284 case Type::FP128TyID: return MVT(MVT::f128);285 case Type::PPC_FP128TyID: return MVT(MVT::ppcf128);286 case Type::FixedVectorTyID:287 case Type::ScalableVectorTyID: {288 VectorType *VTy = cast<VectorType>(Ty);289 return getVectorVT(290 getVT(VTy->getElementType(), /*HandleUnknown=*/ false),291 VTy->getElementCount());292 }293 }294}295 296/// getEVT - Return the value type corresponding to the specified type.297/// If HandleUnknown is true, unknown types are returned as Other, otherwise298/// they are invalid.299/// NB: This includes pointer types, which require a DataLayout to convert300/// to a concrete value type.301EVT EVT::getEVT(Type *Ty, bool HandleUnknown){302 switch (Ty->getTypeID()) {303 default:304 return MVT::getVT(Ty, HandleUnknown);305 case Type::TokenTyID:306 return MVT::Untyped;307 case Type::IntegerTyID:308 return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth());309 case Type::FixedVectorTyID:310 case Type::ScalableVectorTyID: {311 VectorType *VTy = cast<VectorType>(Ty);312 return getVectorVT(Ty->getContext(),313 getEVT(VTy->getElementType(), /*HandleUnknown=*/ false),314 VTy->getElementCount());315 }316 }317}318 319const fltSemantics &MVT::getFltSemantics() const {320 switch (getScalarType().SimpleTy) {321 default: llvm_unreachable("Unknown FP format");322 case MVT::f16: return APFloat::IEEEhalf();323 case MVT::bf16: return APFloat::BFloat();324 case MVT::f32: return APFloat::IEEEsingle();325 case MVT::f64: return APFloat::IEEEdouble();326 case MVT::f80: return APFloat::x87DoubleExtended();327 case MVT::f128: return APFloat::IEEEquad();328 case MVT::ppcf128: return APFloat::PPCDoubleDouble();329 }330}331 332const fltSemantics &EVT::getFltSemantics() const {333 return getScalarType().getSimpleVT().getFltSemantics();334}335 336#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)337void MVT::dump() const {338 print(dbgs());339 dbgs() << "\n";340}341#endif342 343void MVT::print(raw_ostream &OS) const {344 if (SimpleTy == INVALID_SIMPLE_VALUE_TYPE)345 OS << "invalid";346 else347 OS << EVT(*this).getEVTString();348}349