[clang][bytecode] Fix reporting failed local constexpr initializers (#123588)
[llvm-project.git] / llvm / lib / TargetParser / RISCVTargetParser.cpp
blob625645a99e12fcb03089ba06a6e38e47afceeecd
1 //===-- RISCVTargetParser.cpp - Parser for target features ------*- C++ -*-===//
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 // This file implements a target parser to recognise hardware features
10 // for RISC-V CPUs.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/TargetParser/RISCVTargetParser.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/TargetParser/RISCVISAInfo.h"
19 namespace llvm {
20 namespace RISCV {
22 enum CPUKind : unsigned {
23 #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \
24 FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID) \
25 CK_##ENUM,
26 #define TUNE_PROC(ENUM, NAME) CK_##ENUM,
27 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
30 constexpr CPUInfo RISCVCPUInfo[] = {
31 #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \
32 FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID) \
33 { \
34 NAME, \
35 DEFAULT_MARCH, \
36 FAST_SCALAR_UNALIGN, \
37 FAST_VECTOR_UNALIGN, \
38 {MVENDORID, MARCHID, MIMPID}, \
40 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
43 static const CPUInfo *getCPUInfoByName(StringRef CPU) {
44 for (auto &C : RISCVCPUInfo)
45 if (C.Name == CPU)
46 return &C;
47 return nullptr;
50 bool hasFastScalarUnalignedAccess(StringRef CPU) {
51 const CPUInfo *Info = getCPUInfoByName(CPU);
52 return Info && Info->FastScalarUnalignedAccess;
55 bool hasFastVectorUnalignedAccess(StringRef CPU) {
56 const CPUInfo *Info = getCPUInfoByName(CPU);
57 return Info && Info->FastVectorUnalignedAccess;
60 bool hasValidCPUModel(StringRef CPU) {
61 const CPUModel Model = getCPUModel(CPU);
62 return Model.MVendorID != 0 && Model.MArchID != 0 && Model.MImpID != 0;
65 CPUModel getCPUModel(StringRef CPU) {
66 const CPUInfo *Info = getCPUInfoByName(CPU);
67 if (!Info)
68 return {0, 0, 0};
69 return Info->Model;
72 bool parseCPU(StringRef CPU, bool IsRV64) {
73 const CPUInfo *Info = getCPUInfoByName(CPU);
75 if (!Info)
76 return false;
77 return Info->is64Bit() == IsRV64;
80 bool parseTuneCPU(StringRef TuneCPU, bool IsRV64) {
81 std::optional<CPUKind> Kind =
82 llvm::StringSwitch<std::optional<CPUKind>>(TuneCPU)
83 #define TUNE_PROC(ENUM, NAME) .Case(NAME, CK_##ENUM)
84 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
85 .Default(std::nullopt);
87 if (Kind.has_value())
88 return true;
90 // Fallback to parsing as a CPU.
91 return parseCPU(TuneCPU, IsRV64);
94 StringRef getMArchFromMcpu(StringRef CPU) {
95 const CPUInfo *Info = getCPUInfoByName(CPU);
96 if (!Info)
97 return "";
98 return Info->DefaultMarch;
101 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
102 for (const auto &C : RISCVCPUInfo) {
103 if (IsRV64 == C.is64Bit())
104 Values.emplace_back(C.Name);
108 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
109 for (const auto &C : RISCVCPUInfo) {
110 if (IsRV64 == C.is64Bit())
111 Values.emplace_back(C.Name);
113 #define TUNE_PROC(ENUM, NAME) Values.emplace_back(StringRef(NAME));
114 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
117 // This function is currently used by IREE, so it's not dead code.
118 void getFeaturesForCPU(StringRef CPU,
119 SmallVectorImpl<std::string> &EnabledFeatures,
120 bool NeedPlus) {
121 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(CPU);
122 if (MarchFromCPU == "")
123 return;
125 EnabledFeatures.clear();
126 auto RII = RISCVISAInfo::parseArchString(
127 MarchFromCPU, /* EnableExperimentalExtension */ true);
129 if (llvm::errorToBool(RII.takeError()))
130 return;
132 std::vector<std::string> FeatStrings =
133 (*RII)->toFeatures(/* AddAllExtensions */ false);
134 for (const auto &F : FeatStrings)
135 if (NeedPlus)
136 EnabledFeatures.push_back(F);
137 else
138 EnabledFeatures.push_back(F.substr(1));
141 namespace RISCVExtensionBitmaskTable {
142 #define GET_RISCVExtensionBitmaskTable_IMPL
143 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
145 } // namespace RISCVExtensionBitmaskTable
147 namespace {
148 struct LessExtName {
149 bool operator()(const RISCVExtensionBitmaskTable::RISCVExtensionBitmask &LHS,
150 StringRef RHS) {
151 return StringRef(LHS.Name) < RHS;
154 } // namespace
156 } // namespace RISCV
158 namespace RISCVVType {
159 // Encode VTYPE into the binary format used by the the VSETVLI instruction which
160 // is used by our MC layer representation.
162 // Bits | Name | Description
163 // -----+------------+------------------------------------------------
164 // 7 | vma | Vector mask agnostic
165 // 6 | vta | Vector tail agnostic
166 // 5:3 | vsew[2:0] | Standard element width (SEW) setting
167 // 2:0 | vlmul[2:0] | Vector register group multiplier (LMUL) setting
168 unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
169 bool MaskAgnostic) {
170 assert(isValidSEW(SEW) && "Invalid SEW");
171 unsigned VLMULBits = static_cast<unsigned>(VLMUL);
172 unsigned VSEWBits = encodeSEW(SEW);
173 unsigned VTypeI = (VSEWBits << 3) | (VLMULBits & 0x7);
174 if (TailAgnostic)
175 VTypeI |= 0x40;
176 if (MaskAgnostic)
177 VTypeI |= 0x80;
179 return VTypeI;
182 std::pair<unsigned, bool> decodeVLMUL(RISCVII::VLMUL VLMUL) {
183 switch (VLMUL) {
184 default:
185 llvm_unreachable("Unexpected LMUL value!");
186 case RISCVII::VLMUL::LMUL_1:
187 case RISCVII::VLMUL::LMUL_2:
188 case RISCVII::VLMUL::LMUL_4:
189 case RISCVII::VLMUL::LMUL_8:
190 return std::make_pair(1 << static_cast<unsigned>(VLMUL), false);
191 case RISCVII::VLMUL::LMUL_F2:
192 case RISCVII::VLMUL::LMUL_F4:
193 case RISCVII::VLMUL::LMUL_F8:
194 return std::make_pair(1 << (8 - static_cast<unsigned>(VLMUL)), true);
198 void printVType(unsigned VType, raw_ostream &OS) {
199 unsigned Sew = getSEW(VType);
200 OS << "e" << Sew;
202 unsigned LMul;
203 bool Fractional;
204 std::tie(LMul, Fractional) = decodeVLMUL(getVLMUL(VType));
206 if (Fractional)
207 OS << ", mf";
208 else
209 OS << ", m";
210 OS << LMul;
212 if (isTailAgnostic(VType))
213 OS << ", ta";
214 else
215 OS << ", tu";
217 if (isMaskAgnostic(VType))
218 OS << ", ma";
219 else
220 OS << ", mu";
223 unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul) {
224 unsigned LMul;
225 bool Fractional;
226 std::tie(LMul, Fractional) = decodeVLMUL(VLMul);
228 // Convert LMul to a fixed point value with 3 fractional bits.
229 LMul = Fractional ? (8 / LMul) : (LMul * 8);
231 assert(SEW >= 8 && "Unexpected SEW value");
232 return (SEW * 8) / LMul;
235 std::optional<RISCVII::VLMUL>
236 getSameRatioLMUL(unsigned SEW, RISCVII::VLMUL VLMUL, unsigned EEW) {
237 unsigned Ratio = RISCVVType::getSEWLMULRatio(SEW, VLMUL);
238 unsigned EMULFixedPoint = (EEW * 8) / Ratio;
239 bool Fractional = EMULFixedPoint < 8;
240 unsigned EMUL = Fractional ? 8 / EMULFixedPoint : EMULFixedPoint / 8;
241 if (!isValidLMUL(EMUL, Fractional))
242 return std::nullopt;
243 return RISCVVType::encodeLMUL(EMUL, Fractional);
246 } // namespace RISCVVType
248 } // namespace llvm