1 //===-- RISCVTargetParser - 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
14 #ifndef LLVM_TARGETPARSER_RISCVTARGETPARSER_H
15 #define LLVM_TARGETPARSER_RISCVTARGETPARSER_H
16
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 namespace llvm {
23
24 class Triple;
25
26 namespace RISCV {
27
28 struct CPUModel {
29 uint32_t MVendorID;
30 uint64_t MArchID;
31 uint64_t MImpID;
32
isValidCPUModel33 bool isValid() const { return MVendorID != 0 && MArchID != 0 && MImpID != 0; }
34
35 bool operator==(const CPUModel &Other) const {
36 return MVendorID == Other.MVendorID && MArchID == Other.MArchID &&
37 MImpID == Other.MImpID;
38 }
39 };
40
41 struct CPUInfo {
42 StringLiteral Name;
43 StringLiteral DefaultMarch;
44 bool FastScalarUnalignedAccess;
45 bool FastVectorUnalignedAccess;
46 CPUModel Model;
is64BitCPUInfo47 bool is64Bit() const { return DefaultMarch.starts_with("rv64"); }
48 };
49
50 // We use 64 bits as the known part in the scalable vector types.
51 static constexpr unsigned RVVBitsPerBlock = 64;
52 static constexpr unsigned RVVBytesPerBlock = RVVBitsPerBlock / 8;
53
54 LLVM_ABI void getFeaturesForCPU(StringRef CPU,
55 SmallVectorImpl<std::string> &EnabledFeatures,
56 bool NeedPlus = false);
57 LLVM_ABI bool parseCPU(StringRef CPU, bool IsRV64);
58 LLVM_ABI bool parseTuneCPU(StringRef CPU, bool IsRV64);
59 LLVM_ABI StringRef getMArchFromMcpu(StringRef CPU);
60 LLVM_ABI void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values,
61 bool IsRV64);
62 LLVM_ABI void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values,
63 bool IsRV64);
64 LLVM_ABI bool hasFastScalarUnalignedAccess(StringRef CPU);
65 LLVM_ABI bool hasFastVectorUnalignedAccess(StringRef CPU);
66 LLVM_ABI bool hasValidCPUModel(StringRef CPU);
67 LLVM_ABI CPUModel getCPUModel(StringRef CPU);
68 LLVM_ABI StringRef getCPUNameFromCPUModel(const CPUModel &Model);
69
70 } // namespace RISCV
71
72 namespace RISCVVType {
73 enum VLMUL : uint8_t {
74 LMUL_1 = 0,
75 LMUL_2,
76 LMUL_4,
77 LMUL_8,
78 LMUL_RESERVED,
79 LMUL_F8,
80 LMUL_F4,
81 LMUL_F2
82 };
83
84 enum {
85 TAIL_UNDISTURBED_MASK_UNDISTURBED = 0,
86 TAIL_AGNOSTIC = 1,
87 MASK_AGNOSTIC = 2,
88 };
89
90 // Is this a SEW value that can be encoded into the VTYPE format.
isValidSEW(unsigned SEW)91 inline static bool isValidSEW(unsigned SEW) {
92 return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 64;
93 }
94
95 // Is this a LMUL value that can be encoded into the VTYPE format.
isValidLMUL(unsigned LMUL,bool Fractional)96 inline static bool isValidLMUL(unsigned LMUL, bool Fractional) {
97 return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1);
98 }
99
100 LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic,
101 bool MaskAgnostic);
102
103 LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt);
104
getVLMUL(unsigned VType)105 inline static VLMUL getVLMUL(unsigned VType) {
106 unsigned VLMul = VType & 0x7;
107 return static_cast<VLMUL>(VLMul);
108 }
109
110 // Decode VLMUL into 1,2,4,8 and fractional indicator.
111 LLVM_ABI std::pair<unsigned, bool> decodeVLMUL(VLMUL VLMul);
112
encodeLMUL(unsigned LMUL,bool Fractional)113 inline static VLMUL encodeLMUL(unsigned LMUL, bool Fractional) {
114 assert(isValidLMUL(LMUL, Fractional) && "Unsupported LMUL");
115 unsigned LmulLog2 = Log2_32(LMUL);
116 return static_cast<VLMUL>(Fractional ? 8 - LmulLog2 : LmulLog2);
117 }
118
decodeVSEW(unsigned VSEW)119 inline static unsigned decodeVSEW(unsigned VSEW) {
120 assert(VSEW < 8 && "Unexpected VSEW value");
121 return 1 << (VSEW + 3);
122 }
123
encodeSEW(unsigned SEW)124 inline static unsigned encodeSEW(unsigned SEW) {
125 assert(isValidSEW(SEW) && "Unexpected SEW value");
126 return Log2_32(SEW) - 3;
127 }
128
getSEW(unsigned VType)129 inline static unsigned getSEW(unsigned VType) {
130 unsigned VSEW = (VType >> 3) & 0x7;
131 return decodeVSEW(VSEW);
132 }
133
decodeTWiden(unsigned TWiden)134 inline static unsigned decodeTWiden(unsigned TWiden) {
135 assert((TWiden == 1 || TWiden == 2 || TWiden == 3) &&
136 "Unexpected TWiden value");
137 return 1 << (TWiden - 1);
138 }
139
hasXSfmmWiden(unsigned VType)140 inline static bool hasXSfmmWiden(unsigned VType) {
141 unsigned TWiden = (VType >> 9) & 0x3;
142 return TWiden != 0;
143 }
144
getXSfmmWiden(unsigned VType)145 inline static unsigned getXSfmmWiden(unsigned VType) {
146 unsigned TWiden = (VType >> 9) & 0x3;
147 assert(TWiden != 0 && "Invalid widen value");
148 return 1 << (TWiden - 1);
149 }
150
isValidXSfmmVType(unsigned VTypeI)151 static inline bool isValidXSfmmVType(unsigned VTypeI) {
152 return (VTypeI & ~0x738) == 0 && RISCVVType::hasXSfmmWiden(VTypeI) &&
153 RISCVVType::getSEW(VTypeI) * RISCVVType::getXSfmmWiden(VTypeI) <= 64;
154 }
155
isTailAgnostic(unsigned VType)156 inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; }
157
isMaskAgnostic(unsigned VType)158 inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; }
159
isAltFmt(unsigned VType)160 inline static bool isAltFmt(unsigned VType) { return VType & 0x100; }
161
162 LLVM_ABI void printVType(unsigned VType, raw_ostream &OS);
163
164 LLVM_ABI unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul);
165
166 LLVM_ABI std::optional<VLMUL> getSameRatioLMUL(unsigned SEW, VLMUL VLMUL,
167 unsigned EEW);
168 } // namespace RISCVVType
169
170 } // namespace llvm
171
172 #endif
173