Coverage Report

Created: 2022-07-16 07:03

/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 && Scale.value() == 0; }
213
0
  bool isVector() const { return Scale && Scale.value() != 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
0
  bool isPointer() const { return IsPointer; }
229
230
private:
231
  // Verify RVV vector type and set Valid.
232
  bool verifyType() const;
233
234
  // Creates a type based on basic types of TypeRange
235
  void applyBasicType();
236
237
  // Applies a prototype modifier to the current type. The result maybe an
238
  // invalid type.
239
  void applyModifier(const PrototypeDescriptor &prototype);
240
241
  void applyLog2EEW(unsigned Log2EEW);
242
  void applyFixedSEW(unsigned NewSEW);
243
  void applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type);
244
245
  // Compute and record a string for legal type.
246
  void initBuiltinStr();
247
  // Compute and record a builtin RVV vector type string.
248
  void initClangBuiltinStr();
249
  // Compute and record a type string for used in the header.
250
  void initTypeStr();
251
  // Compute and record a short name of a type for C/C++ name suffix.
252
  void initShortStr();
253
254
public:
255
  /// Compute output and input types by applying different config (basic type
256
  /// and LMUL with type transformers). It also record result of type in legal
257
  /// or illegal set to avoid compute the same config again. The result maybe
258
  /// have illegal RVVType.
259
  static llvm::Optional<RVVTypes>
260
  computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
261
               llvm::ArrayRef<PrototypeDescriptor> Prototype);
262
  static llvm::Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL,
263
                                                PrototypeDescriptor Proto);
264
};
265
266
using RISCVPredefinedMacroT = uint8_t;
267
268
enum RISCVPredefinedMacro : RISCVPredefinedMacroT {
269
  Basic = 0,
270
  V = 1 << 1,
271
  Zvfh = 1 << 2,
272
  RV64 = 1 << 3,
273
  VectorMaxELen64 = 1 << 4,
274
  VectorMaxELenFp32 = 1 << 5,
275
  VectorMaxELenFp64 = 1 << 6,
276
};
277
278
enum PolicyScheme : uint8_t {
279
  SchemeNone,
280
  HasPassthruOperand,
281
  HasPolicyOperand,
282
};
283
284
// TODO refactor RVVIntrinsic class design after support all intrinsic
285
// combination. This represents an instantiation of an intrinsic with a
286
// particular type and prototype
287
class RVVIntrinsic {
288
289
private:
290
  std::string BuiltinName; // Builtin name
291
  std::string Name;        // C intrinsic name.
292
  std::string OverloadedName;
293
  std::string IRName;
294
  bool IsMasked;
295
  bool HasVL;
296
  PolicyScheme Scheme;
297
  bool HasUnMaskedOverloaded;
298
  bool HasBuiltinAlias;
299
  std::string ManualCodegen;
300
  RVVTypePtr OutputType; // Builtin output type
301
  RVVTypes InputTypes;   // Builtin input types
302
  // The types we use to obtain the specific LLVM intrinsic. They are index of
303
  // InputTypes. -1 means the return type.
304
  std::vector<int64_t> IntrinsicTypes;
305
  RISCVPredefinedMacroT RISCVPredefinedMacros = 0;
306
  unsigned NF = 1;
307
308
public:
309
  RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix,
310
               llvm::StringRef OverloadedName, llvm::StringRef OverloadedSuffix,
311
               llvm::StringRef IRName, bool IsMasked, bool HasMaskedOffOperand,
312
               bool HasVL, PolicyScheme Scheme, bool HasUnMaskedOverloaded,
313
               bool HasBuiltinAlias, llvm::StringRef ManualCodegen,
314
               const RVVTypes &Types,
315
               const std::vector<int64_t> &IntrinsicTypes,
316
               const std::vector<llvm::StringRef> &RequiredFeatures,
317
               unsigned NF);
318
0
  ~RVVIntrinsic() = default;
319
320
0
  RVVTypePtr getOutputType() const { return OutputType; }
321
0
  const RVVTypes &getInputTypes() const { return InputTypes; }
322
0
  llvm::StringRef getBuiltinName() const { return BuiltinName; }
323
0
  llvm::StringRef getName() const { return Name; }
324
0
  llvm::StringRef getOverloadedName() const { return OverloadedName; }
325
0
  bool hasVL() const { return HasVL; }
326
0
  bool hasPolicy() const { return Scheme != SchemeNone; }
327
0
  bool hasPassthruOperand() const { return Scheme == HasPassthruOperand; }
328
0
  bool hasPolicyOperand() const { return Scheme == HasPolicyOperand; }
329
0
  bool hasUnMaskedOverloaded() const { return HasUnMaskedOverloaded; }
330
0
  bool hasBuiltinAlias() const { return HasBuiltinAlias; }
331
0
  bool hasManualCodegen() const { return !ManualCodegen.empty(); }
332
0
  bool isMasked() const { return IsMasked; }
333
0
  llvm::StringRef getIRName() const { return IRName; }
334
0
  llvm::StringRef getManualCodegen() const { return ManualCodegen; }
335
0
  PolicyScheme getPolicyScheme() const { return Scheme; }
336
0
  RISCVPredefinedMacroT getRISCVPredefinedMacros() const {
337
0
    return RISCVPredefinedMacros;
338
0
  }
339
0
  unsigned getNF() const { return NF; }
340
0
  const std::vector<int64_t> &getIntrinsicTypes() const {
341
0
    return IntrinsicTypes;
342
0
  }
343
344
  // Return the type string for a BUILTIN() macro in Builtins.def.
345
  std::string getBuiltinTypeStr() const;
346
347
  static std::string
348
  getSuffixStr(BasicType Type, int Log2LMUL,
349
               llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors);
350
};
351
352
} // end namespace RISCV
353
354
} // end namespace clang
355
356
#endif // CLANG_SUPPORT_RISCVVINTRINSICUTILS_H