LLVM 20.0.0git
RISCVTargetParser.cpp
Go to the documentation of this file.
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.
11//
12//===----------------------------------------------------------------------===//
13
18
19namespace llvm {
20namespace RISCV {
21
22enum 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"
28};
29
30constexpr 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}, \
39 },
40#include "llvm/TargetParser/RISCVTargetParserDef.inc"
41};
42
44 for (auto &C : RISCVCPUInfo)
45 if (C.Name == CPU)
46 return &C;
47 return nullptr;
48}
49
51 const CPUInfo *Info = getCPUInfoByName(CPU);
52 return Info && Info->FastScalarUnalignedAccess;
53}
54
56 const CPUInfo *Info = getCPUInfoByName(CPU);
57 return Info && Info->FastVectorUnalignedAccess;
58}
59
61 const CPUModel Model = getCPUModel(CPU);
62 return Model.MVendorID != 0 && Model.MArchID != 0 && Model.MImpID != 0;
63}
64
66 const CPUInfo *Info = getCPUInfoByName(CPU);
67 if (!Info)
68 return {0, 0, 0};
69 return Info->Model;
70}
71
72bool parseCPU(StringRef CPU, bool IsRV64) {
73 const CPUInfo *Info = getCPUInfoByName(CPU);
74
75 if (!Info)
76 return false;
77 return Info->is64Bit() == IsRV64;
78}
79
80bool parseTuneCPU(StringRef TuneCPU, bool IsRV64) {
81 std::optional<CPUKind> Kind =
83#define TUNE_PROC(ENUM, NAME) .Case(NAME, CK_##ENUM)
84 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
85 .Default(std::nullopt);
86
87 if (Kind.has_value())
88 return true;
89
90 // Fallback to parsing as a CPU.
91 return parseCPU(TuneCPU, IsRV64);
92}
93
95 const CPUInfo *Info = getCPUInfoByName(CPU);
96 if (!Info)
97 return "";
98 return Info->DefaultMarch;
99}
100
102 for (const auto &C : RISCVCPUInfo) {
103 if (IsRV64 == C.is64Bit())
104 Values.emplace_back(C.Name);
105 }
106}
107
109 for (const auto &C : RISCVCPUInfo) {
110 if (IsRV64 == C.is64Bit())
111 Values.emplace_back(C.Name);
112 }
113#define TUNE_PROC(ENUM, NAME) Values.emplace_back(StringRef(NAME));
114#include "llvm/TargetParser/RISCVTargetParserDef.inc"
115}
116
117// This function is currently used by IREE, so it's not dead code.
119 SmallVectorImpl<std::string> &EnabledFeatures,
120 bool NeedPlus) {
121 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(CPU);
122 if (MarchFromCPU == "")
123 return;
124
125 EnabledFeatures.clear();
127 MarchFromCPU, /* EnableExperimentalExtension */ true);
128
129 if (llvm::errorToBool(RII.takeError()))
130 return;
131
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));
139}
140
141namespace RISCVExtensionBitmaskTable {
142#define GET_RISCVExtensionBitmaskTable_IMPL
143#include "llvm/TargetParser/RISCVTargetParserDef.inc"
144
145} // namespace RISCVExtensionBitmaskTable
146
147namespace {
148struct LessExtName {
149 bool operator()(const RISCVExtensionBitmaskTable::RISCVExtensionBitmask &LHS,
150 StringRef RHS) {
151 return StringRef(LHS.Name) < RHS;
152 }
153};
154} // namespace
155
156} // namespace RISCV
157
158namespace RISCVVType {
159// Encode VTYPE into the binary format used by the the VSETVLI instruction which
160// is used by our MC layer representation.
161//
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
168unsigned 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;
178
179 return VTypeI;
180}
181
182std::pair<unsigned, bool> decodeVLMUL(RISCVII::VLMUL VLMUL) {
183 switch (VLMUL) {
184 default:
185 llvm_unreachable("Unexpected LMUL value!");
190 return std::make_pair(1 << static_cast<unsigned>(VLMUL), false);
194 return std::make_pair(1 << (8 - static_cast<unsigned>(VLMUL)), true);
195 }
196}
197
198void printVType(unsigned VType, raw_ostream &OS) {
199 unsigned Sew = getSEW(VType);
200 OS << "e" << Sew;
201
202 unsigned LMul;
203 bool Fractional;
204 std::tie(LMul, Fractional) = decodeVLMUL(getVLMUL(VType));
205
206 if (Fractional)
207 OS << ", mf";
208 else
209 OS << ", m";
210 OS << LMul;
211
212 if (isTailAgnostic(VType))
213 OS << ", ta";
214 else
215 OS << ", tu";
216
217 if (isMaskAgnostic(VType))
218 OS << ", ma";
219 else
220 OS << ", mu";
221}
222
223unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul) {
224 unsigned LMul;
225 bool Fractional;
226 std::tie(LMul, Fractional) = decodeVLMUL(VLMul);
227
228 // Convert LMul to a fixed point value with 3 fractional bits.
229 LMul = Fractional ? (8 / LMul) : (LMul * 8);
230
231 assert(SEW >= 8 && "Unexpected SEW value");
232 return (SEW * 8) / LMul;
233}
234
235std::optional<RISCVII::VLMUL>
236getSameRatioLMUL(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);
244}
245
246} // namespace RISCVVType
247
248} // namespace llvm
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define ENUM(Name,...)
Definition: ClauseT.h:61
#define F(x, y, z)
Definition: MD5.cpp:55
#define TUNE_PROC(ENUM, NAME)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Value * RHS
Value * LHS
static llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)
Parse RISC-V ISA info from arch string.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:937
void push_back(const T &Elt)
Definition: SmallVector.h:413
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
static bool isTailAgnostic(unsigned VType)
static RISCVII::VLMUL getVLMUL(unsigned VType)
std::pair< unsigned, bool > decodeVLMUL(RISCVII::VLMUL VLMUL)
unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul)
static bool isValidLMUL(unsigned LMUL, bool Fractional)
static RISCVII::VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static bool isMaskAgnostic(unsigned VType)
static unsigned encodeSEW(unsigned SEW)
static bool isValidSEW(unsigned SEW)
void printVType(unsigned VType, raw_ostream &OS)
unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic)
static unsigned getSEW(unsigned VType)
std::optional< RISCVII::VLMUL > getSameRatioLMUL(unsigned SEW, RISCVII::VLMUL VLMUL, unsigned EEW)
bool hasFastVectorUnalignedAccess(StringRef CPU)
void getFeaturesForCPU(StringRef CPU, SmallVectorImpl< std::string > &EnabledFeatures, bool NeedPlus=false)
void fillValidTuneCPUArchList(SmallVectorImpl< StringRef > &Values, bool IsRV64)
static const CPUInfo * getCPUInfoByName(StringRef CPU)
constexpr CPUInfo RISCVCPUInfo[]
CPUModel getCPUModel(StringRef CPU)
StringRef getMArchFromMcpu(StringRef CPU)
bool parseCPU(StringRef CPU, bool IsRV64)
bool hasFastScalarUnalignedAccess(StringRef CPU)
bool hasValidCPUModel(StringRef CPU)
bool parseTuneCPU(StringRef CPU, bool IsRV64)
void fillValidCPUArchList(SmallVectorImpl< StringRef > &Values, bool IsRV64)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:1099