Coverage Report

Created: 2022-05-21 09:15

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h
Line
Count
Source (jump to first uncovered line)
1
//===--- RISCVVIntrinsicUtils.h - RISC-V Vector Intrinsic Utils -*- 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
#ifndef CLANG_SUPPORT_RISCVVINTRINSICUTILS_H
10
#define CLANG_SUPPORT_RISCVVINTRINSICUTILS_H
11
12
#include "llvm/ADT/ArrayRef.h"
13
#include "llvm/ADT/BitmaskEnum.h"
14
#include "llvm/ADT/Optional.h"
15
#include "llvm/ADT/SmallVector.h"
16
#include "llvm/ADT/StringRef.h"
17
#include <cstdint>
18
#include <string>
19
#include <vector>
20
21
namespace clang {
22
namespace RISCV {
23
24
using VScaleVal = llvm::Optional<unsigned>;
25
26
// Modifier for vector type.
27
enum class VectorTypeModifier : uint8_t {
28
  NoModifier,
29
  Widening2XVector,
30
  Widening4XVector,
31
  Widening8XVector,
32
  MaskVector,
33
  Log2EEW3,
34
  Log2EEW4,
35
  Log2EEW5,
36
  Log2EEW6,
37
  FixedSEW8,
38
  FixedSEW16,
39
  FixedSEW32,
40
  FixedSEW64,
41
  LFixedLog2LMULN3,
42
  LFixedLog2LMULN2,
43
  LFixedLog2LMULN1,
44
  LFixedLog2LMUL0,
45
  LFixedLog2LMUL1,
46
  LFixedLog2LMUL2,
47
  LFixedLog2LMUL3,
48
  SFixedLog2LMULN3,
49
  SFixedLog2LMULN2,
50
  SFixedLog2LMULN1,
51
  SFixedLog2LMUL0,
52
  SFixedLog2LMUL1,
53
  SFixedLog2LMUL2,
54
  SFixedLog2LMUL3,
55
};
56
57
// Similar to basic type but used to describe what's kind of type related to
58
// basic vector type, used to compute type info of arguments.
59
enum class BaseTypeModifier : uint8_t {
60
  Invalid,
61
  Scalar,
62
  Vector,
63
  Void,
64
  SizeT,
65
  Ptrdiff,
66
  UnsignedLong,
67
  SignedLong,
68
};
69
70
// Modifier for type, used for both scalar and vector types.
71
enum class TypeModifier : uint8_t {
72
  NoModifier = 0,
73
  Pointer = 1 << 0,
74
  Const = 1 << 1,
75
  Immediate = 1 << 2,
76
  UnsignedInteger = 1 << 3,
77
  SignedInteger = 1 << 4,
78
  Float = 1 << 5,
79
  // LMUL1 should be kind of VectorTypeModifier, but that might come with
80
  // Widening2XVector for widening reduction.
81
  // However that might require VectorTypeModifier become bitmask rather than
82
  // simple enum, so we decide keek LMUL1 in TypeModifier for code size
83
  // optimization of clang binary size.
84
  LMUL1 = 1 << 6,
85
  MaxOffset = 6,
86
  LLVM_MARK_AS_BITMASK_ENUM(LMUL1),
87
};
88
89
// PrototypeDescriptor is used to compute type info of arguments or return
90
// value.
91
struct PrototypeDescriptor {
92
0
  constexpr PrototypeDescriptor() = default;
93
  constexpr PrototypeDescriptor(
94
      BaseTypeModifier PT,
95
      VectorTypeModifier VTM = VectorTypeModifier::NoModifier,
96
      TypeModifier TM = TypeModifier::NoModifier)
97
      : PT(static_cast<uint8_t>(PT)), VTM(static_cast<uint8_t>(VTM)),
98
0
        TM(static_cast<uint8_t>(TM)) {}
99
  constexpr PrototypeDescriptor(uint8_t PT, uint8_t VTM, uint8_t TM)
100
0
      : PT(PT), VTM(VTM), TM(TM) {}
101
102
  uint8_t PT = static_cast<uint8_t>(BaseTypeModifier::Invalid);
103
  uint8_t VTM = static_cast<uint8_t>(VectorTypeModifier::NoModifier);
104
  uint8_t TM = static_cast<uint8_t>(TypeModifier::NoModifier);
105
106
0
  bool operator!=(const PrototypeDescriptor &PD) const {
107
0
    return PD.PT != PT || PD.VTM != VTM || PD.TM != TM;
108
0
  }
109
0
  bool operator>(const PrototypeDescriptor &PD) const {
110
0
    return !(PD.PT <= PT && PD.VTM <= VTM && PD.TM <= TM);
111
0
  }
112
113
  static const PrototypeDescriptor Mask;
114
  static const PrototypeDescriptor Vector;
115
  static const PrototypeDescriptor VL;
116
  static llvm::Optional<PrototypeDescriptor>
117
  parsePrototypeDescriptor(llvm::StringRef PrototypeStr);
118
};
119
120
llvm::SmallVector<PrototypeDescriptor>
121
parsePrototypes(llvm::StringRef Prototypes);
122
123
// Basic type of vector type.
124
enum class BasicType : uint8_t {
125
  Unknown = 0,
126
  Int8 = 1 << 0,
127
  Int16 = 1 << 1,
128
  Int32 = 1 << 2,
129
  Int64 = 1 << 3,
130
  Float16 = 1 << 4,
131
  Float32 = 1 << 5,
132
  Float64 = 1 << 6,
133
  MaxOffset = 6,
134
  LLVM_MARK_AS_BITMASK_ENUM(Float64),
135
};
136
137
// Type of vector type.
138
enum ScalarTypeKind : uint8_t {
139
  Void,
140
  Size_t,
141
  Ptrdiff_t,
142
  UnsignedLong,
143
  SignedLong,
144
  Boolean,
145
  SignedInteger,
146
  UnsignedInteger,
147
  Float,
148
  Invalid,
149
};
150
151
// Exponential LMUL
152
struct LMULType {
153
  int Log2LMUL;
154
  LMULType(int Log2LMUL);
155
  // Return the C/C++ string representation of LMUL
156
  std::string str() const;
157
  llvm::Optional<unsigned> getScale(unsigned ElementBitwidth) const;
158
  void MulLog2LMUL(int Log2LMUL);
159
};
160
161
class RVVType;
162
using RVVTypePtr = RVVType *;
163
using RVVTypes = std::vector<RVVTypePtr>;
164
165
// This class is compact representation of a valid and invalid RVVType.
166
class RVVType {
167
  BasicType BT;
168
  ScalarTypeKind ScalarType = Invalid;
169
  LMULType LMUL;
170
  bool IsPointer = false;
171
  // IsConstant indices are "int", but have the constant expression.
172
  bool IsImmediate = false;
173
  // Const qualifier for pointer to const object or object of const type.
174
  bool IsConstant = false;
175
  unsigned ElementBitwidth = 0;
176
  VScaleVal Scale = 0;
177
  bool Valid;
178
179
  std::string BuiltinStr;
180
  std::string ClangBuiltinStr;
181
  std::string Str;
182
  std::string ShortStr;
183
184
  enum class FixedLMULType { LargerThan, SmallerThan };
185
186
public:
187
0
  RVVType() : BT(BasicType::Unknown), LMUL(0), Valid(false) {}
188
  RVVType(BasicType BT, int Log2LMUL, const PrototypeDescriptor &Profile);
189
190
  // Return the string representation of a type, which is an encoded string for
191
  // passing to the BUILTIN() macro in Builtins.def.
192
0
  const std::string &getBuiltinStr() const { return BuiltinStr; }
193
194
  // Return the clang builtin type for RVV vector type which are used in the
195
  // riscv_vector.h header file.
196
0
  const std::string &getClangBuiltinStr() const { return ClangBuiltinStr; }
197
198
  // Return the C/C++ string representation of a type for use in the
199
  // riscv_vector.h header file.
200
0
  const std::string &getTypeStr() const { return Str; }
201
202
  // Return the short name of a type for C/C++ name suffix.
203
0
  const std::string &getShortStr() {
204
    // Not all types are used in short name, so compute the short name by
205
    // demanded.
206
0
    if (ShortStr.empty())
207
0
      initShortStr();
208
0
    return ShortStr;
209
0
  }
210
211
0
  bool isValid() const { return Valid; }
212
0
  bool isScalar() const { return Scale.hasValue() && Scale.getValue() == 0; }
213
0
  bool isVector() const { return Scale.hasValue() && Scale.getValue() != 0; }
214
0
  bool isVector(unsigned Width) const {
215
0
    return isVector() && ElementBitwidth == Width;
216
0
  }
217
0
  bool isFloat() const { return ScalarType == ScalarTypeKind::Float; }
218
0
  bool isSignedInteger() const {
219
0
    return ScalarType == ScalarTypeKind::SignedInteger;
220
0
  }
221
0
  bool isFloatVector(unsigned Width) const {
222
0
    return isVector() && isFloat() && ElementBitwidth == Width;
223
0
  }
224
0
  bool isFloat(unsigned Width) const {
225
0
    return isFloat() && ElementBitwidth == Width;
226
0
  }
227
228
private:
229
  // Verify RVV vector type and set Valid.
230
  bool verifyType() const;
231
232
  // Creates a type based on basic types of TypeRange
233
  void applyBasicType();
234
235
  // Applies a prototype modifier to the current type. The result maybe an
236
  // invalid type.
237
  void applyModifier(const PrototypeDescriptor &prototype);
238
239
  void applyLog2EEW(unsigned Log2EEW);
240
  void applyFixedSEW(unsigned NewSEW);
241
  void applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type);
242
243
  // Compute and record a string for legal type.
244
  void initBuiltinStr();
245
  // Compute and record a builtin RVV vector type string.
246
  void initClangBuiltinStr();
247
  // Compute and record a type string for used in the header.
248
  void initTypeStr();
249
  // Compute and record a short name of a type for C/C++ name suffix.
250
  void initShortStr();
251
252
public:
253
  /// Compute output and input types by applying different config (basic type
254
  /// and LMUL with type transformers). It also record result of type in legal
255
  /// or illegal set to avoid compute the same config again. The result maybe
256
  /// have illegal RVVType.
257
  static llvm::Optional<RVVTypes>
258
  computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
259
               llvm::ArrayRef<PrototypeDescriptor> PrototypeSeq);
260
  static llvm::Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL,
261
                                                PrototypeDescriptor Proto);
262
};
263
264
using RISCVPredefinedMacroT = uint8_t;
265
266
enum RISCVPredefinedMacro : RISCVPredefinedMacroT {
267
  Basic = 0,
268
  V = 1 << 1,
269
  Zvfh = 1 << 2,
270
  RV64 = 1 << 3,
271
  VectorMaxELen64 = 1 << 4,
272
  VectorMaxELenFp32 = 1 << 5,
273
  VectorMaxELenFp64 = 1 << 6,
274
};
275
276
enum PolicyScheme : uint8_t {
277
  SchemeNone,
278
  HasPassthruOperand,
279
  HasPolicyOperand,
280
};
281
282
// TODO refactor RVVIntrinsic class design after support all intrinsic
283
// combination. This represents an instantiation of an intrinsic with a
284
// particular type and prototype
285
class RVVIntrinsic {
286
287
private:
288
  std::string BuiltinName; // Builtin name
289
  std::string Name;        // C intrinsic name.
290
  std::string MangledName;
291
  std::string IRName;
292
  bool IsMasked;
293
  bool HasVL;
294
  PolicyScheme Scheme;
295
  bool HasUnMaskedOverloaded;
296
  bool HasBuiltinAlias;
297
  std::string ManualCodegen;
298
  RVVTypePtr OutputType; // Builtin output type
299
  RVVTypes InputTypes;   // Builtin input types
300
  // The types we use to obtain the specific LLVM intrinsic. They are index of
301
  // InputTypes. -1 means the return type.
302
  std::vector<int64_t> IntrinsicTypes;
303
  RISCVPredefinedMacroT RISCVPredefinedMacros = 0;
304
  unsigned NF = 1;
305
306
public:
307
  RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix, llvm::StringRef MangledName,
308
               llvm::StringRef MangledSuffix, llvm::StringRef IRName, bool IsMasked,
309
               bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
310
               bool HasUnMaskedOverloaded, bool HasBuiltinAlias,
311
               llvm::StringRef ManualCodegen, const RVVTypes &Types,
312
               const std::vector<int64_t> &IntrinsicTypes,
313
               const std::vector<llvm::StringRef> &RequiredFeatures, unsigned NF);
314
0
  ~RVVIntrinsic() = default;
315
316
0
  RVVTypePtr getOutputType() const { return OutputType; }
317
0
  const RVVTypes &getInputTypes() const { return InputTypes; }
318
0
  llvm::StringRef getBuiltinName() const { return BuiltinName; }
319
0
  llvm::StringRef getName() const { return Name; }
320
0
  llvm::StringRef getMangledName() const { return MangledName; }
321
0
  bool hasVL() const { return HasVL; }
322
0
  bool hasPolicy() const { return Scheme != SchemeNone; }
323
0
  bool hasPassthruOperand() const { return Scheme == HasPassthruOperand; }
324
0
  bool hasPolicyOperand() const { return Scheme == HasPolicyOperand; }
325
0
  bool hasUnMaskedOverloaded() const { return HasUnMaskedOverloaded; }
326
0
  bool hasBuiltinAlias() const { return HasBuiltinAlias; }
327
0
  bool hasManualCodegen() const { return !ManualCodegen.empty(); }
328
0
  bool isMasked() const { return IsMasked; }
329
0
  llvm::StringRef getIRName() const { return IRName; }
330
0
  llvm::StringRef getManualCodegen() const { return ManualCodegen; }
331
0
  PolicyScheme getPolicyScheme() const { return Scheme; }
332
0
  RISCVPredefinedMacroT getRISCVPredefinedMacros() const {
333
0
    return RISCVPredefinedMacros;
334
0
  }
335
0
  unsigned getNF() const { return NF; }
336
0
  const std::vector<int64_t> &getIntrinsicTypes() const {
337
0
    return IntrinsicTypes;
338
0
  }
339
340
  // Return the type string for a BUILTIN() macro in Builtins.def.
341
  std::string getBuiltinTypeStr() const;
342
343
  static std::string getSuffixStr(
344
      BasicType Type, int Log2LMUL,
345
      const llvm::SmallVector<PrototypeDescriptor> &PrototypeDescriptors);
346
};
347
348
} // end namespace RISCV
349
350
} // end namespace clang
351
352
#endif // CLANG_SUPPORT_RISCVVINTRINSICUTILS_H