Path: blob/main/contrib/llvm-project/llvm/lib/TargetParser/RISCVTargetParser.cpp
35234 views
//===-- RISCVTargetParser.cpp - Parser for target features ------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements a target parser to recognise hardware features9// for RISC-V CPUs.10//11//===----------------------------------------------------------------------===//1213#include "llvm/TargetParser/RISCVTargetParser.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/ADT/StringSwitch.h"16#include "llvm/TargetParser/RISCVISAInfo.h"17#include "llvm/TargetParser/Triple.h"1819namespace llvm {20namespace RISCV {2122enum CPUKind : unsigned {23#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \24FAST_VECTOR_UNALIGN) \25CK_##ENUM,26#define TUNE_PROC(ENUM, NAME) CK_##ENUM,27#include "llvm/TargetParser/RISCVTargetParserDef.inc"28};2930struct CPUInfo {31StringLiteral Name;32StringLiteral DefaultMarch;33bool FastScalarUnalignedAccess;34bool FastVectorUnalignedAccess;35bool is64Bit() const { return DefaultMarch.starts_with("rv64"); }36};3738constexpr CPUInfo RISCVCPUInfo[] = {39#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \40FAST_VECTOR_UNALIGN) \41{NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, FAST_VECTOR_UNALIGN},42#include "llvm/TargetParser/RISCVTargetParserDef.inc"43};4445static const CPUInfo *getCPUInfoByName(StringRef CPU) {46for (auto &C : RISCVCPUInfo)47if (C.Name == CPU)48return &C;49return nullptr;50}5152bool hasFastScalarUnalignedAccess(StringRef CPU) {53const CPUInfo *Info = getCPUInfoByName(CPU);54return Info && Info->FastScalarUnalignedAccess;55}5657bool hasFastVectorUnalignedAccess(StringRef CPU) {58const CPUInfo *Info = getCPUInfoByName(CPU);59return Info && Info->FastVectorUnalignedAccess;60}6162bool parseCPU(StringRef CPU, bool IsRV64) {63const CPUInfo *Info = getCPUInfoByName(CPU);6465if (!Info)66return false;67return Info->is64Bit() == IsRV64;68}6970bool parseTuneCPU(StringRef TuneCPU, bool IsRV64) {71std::optional<CPUKind> Kind =72llvm::StringSwitch<std::optional<CPUKind>>(TuneCPU)73#define TUNE_PROC(ENUM, NAME) .Case(NAME, CK_##ENUM)74#include "llvm/TargetParser/RISCVTargetParserDef.inc"75.Default(std::nullopt);7677if (Kind.has_value())78return true;7980// Fallback to parsing as a CPU.81return parseCPU(TuneCPU, IsRV64);82}8384StringRef getMArchFromMcpu(StringRef CPU) {85const CPUInfo *Info = getCPUInfoByName(CPU);86if (!Info)87return "";88return Info->DefaultMarch;89}9091void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {92for (const auto &C : RISCVCPUInfo) {93if (IsRV64 == C.is64Bit())94Values.emplace_back(C.Name);95}96}9798void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {99for (const auto &C : RISCVCPUInfo) {100if (IsRV64 == C.is64Bit())101Values.emplace_back(C.Name);102}103#define TUNE_PROC(ENUM, NAME) Values.emplace_back(StringRef(NAME));104#include "llvm/TargetParser/RISCVTargetParserDef.inc"105}106107// This function is currently used by IREE, so it's not dead code.108void getFeaturesForCPU(StringRef CPU,109SmallVectorImpl<std::string> &EnabledFeatures,110bool NeedPlus) {111StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(CPU);112if (MarchFromCPU == "")113return;114115EnabledFeatures.clear();116auto RII = RISCVISAInfo::parseArchString(117MarchFromCPU, /* EnableExperimentalExtension */ true);118119if (llvm::errorToBool(RII.takeError()))120return;121122std::vector<std::string> FeatStrings =123(*RII)->toFeatures(/* AddAllExtensions */ false);124for (const auto &F : FeatStrings)125if (NeedPlus)126EnabledFeatures.push_back(F);127else128EnabledFeatures.push_back(F.substr(1));129}130131namespace RISCVExtensionBitmaskTable {132#define GET_RISCVExtensionBitmaskTable_IMPL133#include "llvm/TargetParser/RISCVTargetParserDef.inc"134135} // namespace RISCVExtensionBitmaskTable136137namespace {138struct LessExtName {139bool operator()(const RISCVExtensionBitmaskTable::RISCVExtensionBitmask &LHS,140StringRef RHS) {141return StringRef(LHS.Name) < RHS;142}143};144} // namespace145146} // namespace RISCV147148namespace RISCVVType {149// Encode VTYPE into the binary format used by the the VSETVLI instruction which150// is used by our MC layer representation.151//152// Bits | Name | Description153// -----+------------+------------------------------------------------154// 7 | vma | Vector mask agnostic155// 6 | vta | Vector tail agnostic156// 5:3 | vsew[2:0] | Standard element width (SEW) setting157// 2:0 | vlmul[2:0] | Vector register group multiplier (LMUL) setting158unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic,159bool MaskAgnostic) {160assert(isValidSEW(SEW) && "Invalid SEW");161unsigned VLMULBits = static_cast<unsigned>(VLMUL);162unsigned VSEWBits = encodeSEW(SEW);163unsigned VTypeI = (VSEWBits << 3) | (VLMULBits & 0x7);164if (TailAgnostic)165VTypeI |= 0x40;166if (MaskAgnostic)167VTypeI |= 0x80;168169return VTypeI;170}171172std::pair<unsigned, bool> decodeVLMUL(RISCVII::VLMUL VLMUL) {173switch (VLMUL) {174default:175llvm_unreachable("Unexpected LMUL value!");176case RISCVII::VLMUL::LMUL_1:177case RISCVII::VLMUL::LMUL_2:178case RISCVII::VLMUL::LMUL_4:179case RISCVII::VLMUL::LMUL_8:180return std::make_pair(1 << static_cast<unsigned>(VLMUL), false);181case RISCVII::VLMUL::LMUL_F2:182case RISCVII::VLMUL::LMUL_F4:183case RISCVII::VLMUL::LMUL_F8:184return std::make_pair(1 << (8 - static_cast<unsigned>(VLMUL)), true);185}186}187188void printVType(unsigned VType, raw_ostream &OS) {189unsigned Sew = getSEW(VType);190OS << "e" << Sew;191192unsigned LMul;193bool Fractional;194std::tie(LMul, Fractional) = decodeVLMUL(getVLMUL(VType));195196if (Fractional)197OS << ", mf";198else199OS << ", m";200OS << LMul;201202if (isTailAgnostic(VType))203OS << ", ta";204else205OS << ", tu";206207if (isMaskAgnostic(VType))208OS << ", ma";209else210OS << ", mu";211}212213unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul) {214unsigned LMul;215bool Fractional;216std::tie(LMul, Fractional) = decodeVLMUL(VLMul);217218// Convert LMul to a fixed point value with 3 fractional bits.219LMul = Fractional ? (8 / LMul) : (LMul * 8);220221assert(SEW >= 8 && "Unexpected SEW value");222return (SEW * 8) / LMul;223}224225std::optional<RISCVII::VLMUL>226getSameRatioLMUL(unsigned SEW, RISCVII::VLMUL VLMUL, unsigned EEW) {227unsigned Ratio = RISCVVType::getSEWLMULRatio(SEW, VLMUL);228unsigned EMULFixedPoint = (EEW * 8) / Ratio;229bool Fractional = EMULFixedPoint < 8;230unsigned EMUL = Fractional ? 8 / EMULFixedPoint : EMULFixedPoint / 8;231if (!isValidLMUL(EMUL, Fractional))232return std::nullopt;233return RISCVVType::encodeLMUL(EMUL, Fractional);234}235236} // namespace RISCVVType237238} // namespace llvm239240241