Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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/SmallVector.h" |
||
| 15 | #include "llvm/ADT/StringRef.h" |
||
| 16 | #include <cstdint> |
||
| 17 | #include <optional> |
||
| 18 | #include <set> |
||
| 19 | #include <string> |
||
| 20 | #include <unordered_map> |
||
| 21 | #include <vector> |
||
| 22 | |||
| 23 | namespace llvm { |
||
| 24 | class raw_ostream; |
||
| 25 | } // end namespace llvm |
||
| 26 | |||
| 27 | namespace clang { |
||
| 28 | namespace RISCV { |
||
| 29 | |||
| 30 | using VScaleVal = std::optional<unsigned>; |
||
| 31 | |||
| 32 | // Modifier for vector type. |
||
| 33 | enum class VectorTypeModifier : uint8_t { |
||
| 34 | NoModifier, |
||
| 35 | Widening2XVector, |
||
| 36 | Widening4XVector, |
||
| 37 | Widening8XVector, |
||
| 38 | MaskVector, |
||
| 39 | Log2EEW3, |
||
| 40 | Log2EEW4, |
||
| 41 | Log2EEW5, |
||
| 42 | Log2EEW6, |
||
| 43 | FixedSEW8, |
||
| 44 | FixedSEW16, |
||
| 45 | FixedSEW32, |
||
| 46 | FixedSEW64, |
||
| 47 | LFixedLog2LMULN3, |
||
| 48 | LFixedLog2LMULN2, |
||
| 49 | LFixedLog2LMULN1, |
||
| 50 | LFixedLog2LMUL0, |
||
| 51 | LFixedLog2LMUL1, |
||
| 52 | LFixedLog2LMUL2, |
||
| 53 | LFixedLog2LMUL3, |
||
| 54 | SFixedLog2LMULN3, |
||
| 55 | SFixedLog2LMULN2, |
||
| 56 | SFixedLog2LMULN1, |
||
| 57 | SFixedLog2LMUL0, |
||
| 58 | SFixedLog2LMUL1, |
||
| 59 | SFixedLog2LMUL2, |
||
| 60 | SFixedLog2LMUL3, |
||
| 61 | }; |
||
| 62 | |||
| 63 | // Similar to basic type but used to describe what's kind of type related to |
||
| 64 | // basic vector type, used to compute type info of arguments. |
||
| 65 | enum class BaseTypeModifier : uint8_t { |
||
| 66 | Invalid, |
||
| 67 | Scalar, |
||
| 68 | Vector, |
||
| 69 | Void, |
||
| 70 | SizeT, |
||
| 71 | Ptrdiff, |
||
| 72 | UnsignedLong, |
||
| 73 | SignedLong, |
||
| 74 | }; |
||
| 75 | |||
| 76 | // Modifier for type, used for both scalar and vector types. |
||
| 77 | enum class TypeModifier : uint8_t { |
||
| 78 | NoModifier = 0, |
||
| 79 | Pointer = 1 << 0, |
||
| 80 | Const = 1 << 1, |
||
| 81 | Immediate = 1 << 2, |
||
| 82 | UnsignedInteger = 1 << 3, |
||
| 83 | SignedInteger = 1 << 4, |
||
| 84 | Float = 1 << 5, |
||
| 85 | // LMUL1 should be kind of VectorTypeModifier, but that might come with |
||
| 86 | // Widening2XVector for widening reduction. |
||
| 87 | // However that might require VectorTypeModifier become bitmask rather than |
||
| 88 | // simple enum, so we decide keek LMUL1 in TypeModifier for code size |
||
| 89 | // optimization of clang binary size. |
||
| 90 | LMUL1 = 1 << 6, |
||
| 91 | MaxOffset = 6, |
||
| 92 | LLVM_MARK_AS_BITMASK_ENUM(LMUL1), |
||
| 93 | }; |
||
| 94 | |||
| 95 | class Policy { |
||
| 96 | public: |
||
| 97 | enum PolicyType { |
||
| 98 | Undisturbed, |
||
| 99 | Agnostic, |
||
| 100 | }; |
||
| 101 | |||
| 102 | private: |
||
| 103 | // The default assumption for an RVV instruction is TAMA, as an undisturbed |
||
| 104 | // policy generally will affect the performance of an out-of-order core. |
||
| 105 | const PolicyType TailPolicy = Agnostic; |
||
| 106 | const PolicyType MaskPolicy = Agnostic; |
||
| 107 | |||
| 108 | public: |
||
| 109 | Policy() = default; |
||
| 110 | Policy(PolicyType TailPolicy) : TailPolicy(TailPolicy) {} |
||
| 111 | Policy(PolicyType TailPolicy, PolicyType MaskPolicy) |
||
| 112 | : TailPolicy(TailPolicy), MaskPolicy(MaskPolicy) {} |
||
| 113 | |||
| 114 | bool isTAMAPolicy() const { |
||
| 115 | return TailPolicy == Agnostic && MaskPolicy == Agnostic; |
||
| 116 | } |
||
| 117 | |||
| 118 | bool isTAMUPolicy() const { |
||
| 119 | return TailPolicy == Agnostic && MaskPolicy == Undisturbed; |
||
| 120 | } |
||
| 121 | |||
| 122 | bool isTUMAPolicy() const { |
||
| 123 | return TailPolicy == Undisturbed && MaskPolicy == Agnostic; |
||
| 124 | } |
||
| 125 | |||
| 126 | bool isTUMUPolicy() const { |
||
| 127 | return TailPolicy == Undisturbed && MaskPolicy == Undisturbed; |
||
| 128 | } |
||
| 129 | |||
| 130 | bool isTAPolicy() const { return TailPolicy == Agnostic; } |
||
| 131 | |||
| 132 | bool isTUPolicy() const { return TailPolicy == Undisturbed; } |
||
| 133 | |||
| 134 | bool isMAPolicy() const { return MaskPolicy == Agnostic; } |
||
| 135 | |||
| 136 | bool isMUPolicy() const { return MaskPolicy == Undisturbed; } |
||
| 137 | |||
| 138 | bool operator==(const Policy &Other) const { |
||
| 139 | return TailPolicy == Other.TailPolicy && MaskPolicy == Other.MaskPolicy; |
||
| 140 | } |
||
| 141 | |||
| 142 | bool operator!=(const Policy &Other) const { return !(*this == Other); } |
||
| 143 | |||
| 144 | bool operator<(const Policy &Other) const { |
||
| 145 | // Just for maintain the old order for quick test. |
||
| 146 | if (MaskPolicy != Other.MaskPolicy) |
||
| 147 | return Other.MaskPolicy < MaskPolicy; |
||
| 148 | return TailPolicy < Other.TailPolicy; |
||
| 149 | } |
||
| 150 | }; |
||
| 151 | |||
| 152 | // PrototypeDescriptor is used to compute type info of arguments or return |
||
| 153 | // value. |
||
| 154 | struct PrototypeDescriptor { |
||
| 155 | constexpr PrototypeDescriptor() = default; |
||
| 156 | constexpr PrototypeDescriptor( |
||
| 157 | BaseTypeModifier PT, |
||
| 158 | VectorTypeModifier VTM = VectorTypeModifier::NoModifier, |
||
| 159 | TypeModifier TM = TypeModifier::NoModifier) |
||
| 160 | : PT(static_cast<uint8_t>(PT)), VTM(static_cast<uint8_t>(VTM)), |
||
| 161 | TM(static_cast<uint8_t>(TM)) {} |
||
| 162 | constexpr PrototypeDescriptor(uint8_t PT, uint8_t VTM, uint8_t TM) |
||
| 163 | : PT(PT), VTM(VTM), TM(TM) {} |
||
| 164 | |||
| 165 | uint8_t PT = static_cast<uint8_t>(BaseTypeModifier::Invalid); |
||
| 166 | uint8_t VTM = static_cast<uint8_t>(VectorTypeModifier::NoModifier); |
||
| 167 | uint8_t TM = static_cast<uint8_t>(TypeModifier::NoModifier); |
||
| 168 | |||
| 169 | bool operator!=(const PrototypeDescriptor &PD) const { |
||
| 170 | return !(*this == PD); |
||
| 171 | } |
||
| 172 | bool operator==(const PrototypeDescriptor &PD) const { |
||
| 173 | return PD.PT == PT && PD.VTM == VTM && PD.TM == TM; |
||
| 174 | } |
||
| 175 | bool operator<(const PrototypeDescriptor &PD) const { |
||
| 176 | return std::tie(PT, VTM, TM) < std::tie(PD.PT, PD.VTM, PD.TM); |
||
| 177 | } |
||
| 178 | static const PrototypeDescriptor Mask; |
||
| 179 | static const PrototypeDescriptor Vector; |
||
| 180 | static const PrototypeDescriptor VL; |
||
| 181 | static std::optional<PrototypeDescriptor> |
||
| 182 | parsePrototypeDescriptor(llvm::StringRef PrototypeStr); |
||
| 183 | }; |
||
| 184 | |||
| 185 | llvm::SmallVector<PrototypeDescriptor> |
||
| 186 | parsePrototypes(llvm::StringRef Prototypes); |
||
| 187 | |||
| 188 | // Basic type of vector type. |
||
| 189 | enum class BasicType : uint8_t { |
||
| 190 | Unknown = 0, |
||
| 191 | Int8 = 1 << 0, |
||
| 192 | Int16 = 1 << 1, |
||
| 193 | Int32 = 1 << 2, |
||
| 194 | Int64 = 1 << 3, |
||
| 195 | Float16 = 1 << 4, |
||
| 196 | Float32 = 1 << 5, |
||
| 197 | Float64 = 1 << 6, |
||
| 198 | MaxOffset = 6, |
||
| 199 | LLVM_MARK_AS_BITMASK_ENUM(Float64), |
||
| 200 | }; |
||
| 201 | |||
| 202 | // Type of vector type. |
||
| 203 | enum ScalarTypeKind : uint8_t { |
||
| 204 | Void, |
||
| 205 | Size_t, |
||
| 206 | Ptrdiff_t, |
||
| 207 | UnsignedLong, |
||
| 208 | SignedLong, |
||
| 209 | Boolean, |
||
| 210 | SignedInteger, |
||
| 211 | UnsignedInteger, |
||
| 212 | Float, |
||
| 213 | Invalid, |
||
| 214 | }; |
||
| 215 | |||
| 216 | // Exponential LMUL |
||
| 217 | struct LMULType { |
||
| 218 | int Log2LMUL; |
||
| 219 | LMULType(int Log2LMUL); |
||
| 220 | // Return the C/C++ string representation of LMUL |
||
| 221 | std::string str() const; |
||
| 222 | std::optional<unsigned> getScale(unsigned ElementBitwidth) const; |
||
| 223 | void MulLog2LMUL(int Log2LMUL); |
||
| 224 | }; |
||
| 225 | |||
| 226 | class RVVType; |
||
| 227 | using RVVTypePtr = RVVType *; |
||
| 228 | using RVVTypes = std::vector<RVVTypePtr>; |
||
| 229 | class RVVTypeCache; |
||
| 230 | |||
| 231 | // This class is compact representation of a valid and invalid RVVType. |
||
| 232 | class RVVType { |
||
| 233 | friend class RVVTypeCache; |
||
| 234 | |||
| 235 | BasicType BT; |
||
| 236 | ScalarTypeKind ScalarType = Invalid; |
||
| 237 | LMULType LMUL; |
||
| 238 | bool IsPointer = false; |
||
| 239 | // IsConstant indices are "int", but have the constant expression. |
||
| 240 | bool IsImmediate = false; |
||
| 241 | // Const qualifier for pointer to const object or object of const type. |
||
| 242 | bool IsConstant = false; |
||
| 243 | unsigned ElementBitwidth = 0; |
||
| 244 | VScaleVal Scale = 0; |
||
| 245 | bool Valid; |
||
| 246 | |||
| 247 | std::string BuiltinStr; |
||
| 248 | std::string ClangBuiltinStr; |
||
| 249 | std::string Str; |
||
| 250 | std::string ShortStr; |
||
| 251 | |||
| 252 | enum class FixedLMULType { LargerThan, SmallerThan }; |
||
| 253 | |||
| 254 | RVVType(BasicType BT, int Log2LMUL, const PrototypeDescriptor &Profile); |
||
| 255 | |||
| 256 | public: |
||
| 257 | // Return the string representation of a type, which is an encoded string for |
||
| 258 | // passing to the BUILTIN() macro in Builtins.def. |
||
| 259 | const std::string &getBuiltinStr() const { return BuiltinStr; } |
||
| 260 | |||
| 261 | // Return the clang builtin type for RVV vector type which are used in the |
||
| 262 | // riscv_vector.h header file. |
||
| 263 | const std::string &getClangBuiltinStr() const { return ClangBuiltinStr; } |
||
| 264 | |||
| 265 | // Return the C/C++ string representation of a type for use in the |
||
| 266 | // riscv_vector.h header file. |
||
| 267 | const std::string &getTypeStr() const { return Str; } |
||
| 268 | |||
| 269 | // Return the short name of a type for C/C++ name suffix. |
||
| 270 | const std::string &getShortStr() { |
||
| 271 | // Not all types are used in short name, so compute the short name by |
||
| 272 | // demanded. |
||
| 273 | if (ShortStr.empty()) |
||
| 274 | initShortStr(); |
||
| 275 | return ShortStr; |
||
| 276 | } |
||
| 277 | |||
| 278 | bool isValid() const { return Valid; } |
||
| 279 | bool isScalar() const { return Scale && *Scale == 0; } |
||
| 280 | bool isVector() const { return Scale && *Scale != 0; } |
||
| 281 | bool isVector(unsigned Width) const { |
||
| 282 | return isVector() && ElementBitwidth == Width; |
||
| 283 | } |
||
| 284 | bool isFloat() const { return ScalarType == ScalarTypeKind::Float; } |
||
| 285 | bool isSignedInteger() const { |
||
| 286 | return ScalarType == ScalarTypeKind::SignedInteger; |
||
| 287 | } |
||
| 288 | bool isFloatVector(unsigned Width) const { |
||
| 289 | return isVector() && isFloat() && ElementBitwidth == Width; |
||
| 290 | } |
||
| 291 | bool isFloat(unsigned Width) const { |
||
| 292 | return isFloat() && ElementBitwidth == Width; |
||
| 293 | } |
||
| 294 | bool isConstant() const { return IsConstant; } |
||
| 295 | bool isPointer() const { return IsPointer; } |
||
| 296 | unsigned getElementBitwidth() const { return ElementBitwidth; } |
||
| 297 | |||
| 298 | ScalarTypeKind getScalarType() const { return ScalarType; } |
||
| 299 | VScaleVal getScale() const { return Scale; } |
||
| 300 | |||
| 301 | private: |
||
| 302 | // Verify RVV vector type and set Valid. |
||
| 303 | bool verifyType() const; |
||
| 304 | |||
| 305 | // Creates a type based on basic types of TypeRange |
||
| 306 | void applyBasicType(); |
||
| 307 | |||
| 308 | // Applies a prototype modifier to the current type. The result maybe an |
||
| 309 | // invalid type. |
||
| 310 | void applyModifier(const PrototypeDescriptor &prototype); |
||
| 311 | |||
| 312 | void applyLog2EEW(unsigned Log2EEW); |
||
| 313 | void applyFixedSEW(unsigned NewSEW); |
||
| 314 | void applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type); |
||
| 315 | |||
| 316 | // Compute and record a string for legal type. |
||
| 317 | void initBuiltinStr(); |
||
| 318 | // Compute and record a builtin RVV vector type string. |
||
| 319 | void initClangBuiltinStr(); |
||
| 320 | // Compute and record a type string for used in the header. |
||
| 321 | void initTypeStr(); |
||
| 322 | // Compute and record a short name of a type for C/C++ name suffix. |
||
| 323 | void initShortStr(); |
||
| 324 | }; |
||
| 325 | |||
| 326 | // This class is used to manage RVVType, RVVType should only created by this |
||
| 327 | // class, also provided thread-safe cache capability. |
||
| 328 | class RVVTypeCache { |
||
| 329 | private: |
||
| 330 | std::unordered_map<uint64_t, RVVType> LegalTypes; |
||
| 331 | std::set<uint64_t> IllegalTypes; |
||
| 332 | |||
| 333 | public: |
||
| 334 | /// Compute output and input types by applying different config (basic type |
||
| 335 | /// and LMUL with type transformers). It also record result of type in legal |
||
| 336 | /// or illegal set to avoid compute the same config again. The result maybe |
||
| 337 | /// have illegal RVVType. |
||
| 338 | std::optional<RVVTypes> |
||
| 339 | computeTypes(BasicType BT, int Log2LMUL, unsigned NF, |
||
| 340 | llvm::ArrayRef<PrototypeDescriptor> Prototype); |
||
| 341 | std::optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL, |
||
| 342 | PrototypeDescriptor Proto); |
||
| 343 | }; |
||
| 344 | |||
| 345 | enum PolicyScheme : uint8_t { |
||
| 346 | SchemeNone, |
||
| 347 | // Passthru operand is at first parameter in C builtin. |
||
| 348 | HasPassthruOperand, |
||
| 349 | HasPolicyOperand, |
||
| 350 | }; |
||
| 351 | |||
| 352 | // TODO refactor RVVIntrinsic class design after support all intrinsic |
||
| 353 | // combination. This represents an instantiation of an intrinsic with a |
||
| 354 | // particular type and prototype |
||
| 355 | class RVVIntrinsic { |
||
| 356 | |||
| 357 | private: |
||
| 358 | std::string BuiltinName; // Builtin name |
||
| 359 | std::string Name; // C intrinsic name. |
||
| 360 | std::string OverloadedName; |
||
| 361 | std::string IRName; |
||
| 362 | bool IsMasked; |
||
| 363 | bool HasMaskedOffOperand; |
||
| 364 | bool HasVL; |
||
| 365 | PolicyScheme Scheme; |
||
| 366 | bool SupportOverloading; |
||
| 367 | bool HasBuiltinAlias; |
||
| 368 | std::string ManualCodegen; |
||
| 369 | RVVTypePtr OutputType; // Builtin output type |
||
| 370 | RVVTypes InputTypes; // Builtin input types |
||
| 371 | // The types we use to obtain the specific LLVM intrinsic. They are index of |
||
| 372 | // InputTypes. -1 means the return type. |
||
| 373 | std::vector<int64_t> IntrinsicTypes; |
||
| 374 | unsigned NF = 1; |
||
| 375 | Policy PolicyAttrs; |
||
| 376 | |||
| 377 | public: |
||
| 378 | RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix, |
||
| 379 | llvm::StringRef OverloadedName, llvm::StringRef OverloadedSuffix, |
||
| 380 | llvm::StringRef IRName, bool IsMasked, bool HasMaskedOffOperand, |
||
| 381 | bool HasVL, PolicyScheme Scheme, bool SupportOverloading, |
||
| 382 | bool HasBuiltinAlias, llvm::StringRef ManualCodegen, |
||
| 383 | const RVVTypes &Types, |
||
| 384 | const std::vector<int64_t> &IntrinsicTypes, |
||
| 385 | const std::vector<llvm::StringRef> &RequiredFeatures, |
||
| 386 | unsigned NF, Policy PolicyAttrs); |
||
| 387 | ~RVVIntrinsic() = default; |
||
| 388 | |||
| 389 | RVVTypePtr getOutputType() const { return OutputType; } |
||
| 390 | const RVVTypes &getInputTypes() const { return InputTypes; } |
||
| 391 | llvm::StringRef getBuiltinName() const { return BuiltinName; } |
||
| 392 | llvm::StringRef getName() const { return Name; } |
||
| 393 | llvm::StringRef getOverloadedName() const { return OverloadedName; } |
||
| 394 | bool hasMaskedOffOperand() const { return HasMaskedOffOperand; } |
||
| 395 | bool hasVL() const { return HasVL; } |
||
| 396 | bool hasPolicy() const { return Scheme != PolicyScheme::SchemeNone; } |
||
| 397 | bool hasPassthruOperand() const { |
||
| 398 | return Scheme == PolicyScheme::HasPassthruOperand; |
||
| 399 | } |
||
| 400 | bool hasPolicyOperand() const { |
||
| 401 | return Scheme == PolicyScheme::HasPolicyOperand; |
||
| 402 | } |
||
| 403 | bool supportOverloading() const { return SupportOverloading; } |
||
| 404 | bool hasBuiltinAlias() const { return HasBuiltinAlias; } |
||
| 405 | bool hasManualCodegen() const { return !ManualCodegen.empty(); } |
||
| 406 | bool isMasked() const { return IsMasked; } |
||
| 407 | llvm::StringRef getIRName() const { return IRName; } |
||
| 408 | llvm::StringRef getManualCodegen() const { return ManualCodegen; } |
||
| 409 | PolicyScheme getPolicyScheme() const { return Scheme; } |
||
| 410 | unsigned getNF() const { return NF; } |
||
| 411 | const std::vector<int64_t> &getIntrinsicTypes() const { |
||
| 412 | return IntrinsicTypes; |
||
| 413 | } |
||
| 414 | Policy getPolicyAttrs() const { |
||
| 415 | return PolicyAttrs; |
||
| 416 | } |
||
| 417 | unsigned getPolicyAttrsBits() const { |
||
| 418 | // CGBuiltin.cpp |
||
| 419 | // The 0th bit simulates the `vta` of RVV |
||
| 420 | // The 1st bit simulates the `vma` of RVV |
||
| 421 | // int PolicyAttrs = 0; |
||
| 422 | |||
| 423 | if (PolicyAttrs.isTUMAPolicy()) |
||
| 424 | return 2; |
||
| 425 | if (PolicyAttrs.isTAMAPolicy()) |
||
| 426 | return 3; |
||
| 427 | if (PolicyAttrs.isTUMUPolicy()) |
||
| 428 | return 0; |
||
| 429 | if (PolicyAttrs.isTAMUPolicy()) |
||
| 430 | return 1; |
||
| 431 | |||
| 432 | llvm_unreachable("unsupport policy"); |
||
| 433 | return 0; |
||
| 434 | } |
||
| 435 | |||
| 436 | // Return the type string for a BUILTIN() macro in Builtins.def. |
||
| 437 | std::string getBuiltinTypeStr() const; |
||
| 438 | |||
| 439 | static std::string |
||
| 440 | getSuffixStr(RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, |
||
| 441 | llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors); |
||
| 442 | |||
| 443 | static llvm::SmallVector<PrototypeDescriptor> |
||
| 444 | computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype, |
||
| 445 | bool IsMasked, bool HasMaskedOffOperand, bool HasVL, |
||
| 446 | unsigned NF, PolicyScheme DefaultScheme, |
||
| 447 | Policy PolicyAttrs); |
||
| 448 | |||
| 449 | static llvm::SmallVector<Policy> getSupportedUnMaskedPolicies(); |
||
| 450 | static llvm::SmallVector<Policy> |
||
| 451 | getSupportedMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy); |
||
| 452 | |||
| 453 | static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy, |
||
| 454 | std::string &Name, std::string &BuiltinName, |
||
| 455 | std::string &OverloadedName, |
||
| 456 | Policy &PolicyAttrs); |
||
| 457 | }; |
||
| 458 | |||
| 459 | // RVVRequire should be sync'ed with target features, but only |
||
| 460 | // required features used in riscv_vector.td. |
||
| 461 | enum RVVRequire : uint8_t { |
||
| 462 | RVV_REQ_None = 0, |
||
| 463 | RVV_REQ_RV64 = 1 << 0, |
||
| 464 | RVV_REQ_FullMultiply = 1 << 1, |
||
| 465 | |||
| 466 | LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_FullMultiply) |
||
| 467 | }; |
||
| 468 | |||
| 469 | // Raw RVV intrinsic info, used to expand later. |
||
| 470 | // This struct is highly compact for minimized code size. |
||
| 471 | struct RVVIntrinsicRecord { |
||
| 472 | // Intrinsic name, e.g. vadd_vv |
||
| 473 | const char *Name; |
||
| 474 | |||
| 475 | // Overloaded intrinsic name, could be empty if it can be computed from Name. |
||
| 476 | // e.g. vadd |
||
| 477 | const char *OverloadedName; |
||
| 478 | |||
| 479 | // Prototype for this intrinsic, index of RVVSignatureTable. |
||
| 480 | uint16_t PrototypeIndex; |
||
| 481 | |||
| 482 | // Suffix of intrinsic name, index of RVVSignatureTable. |
||
| 483 | uint16_t SuffixIndex; |
||
| 484 | |||
| 485 | // Suffix of overloaded intrinsic name, index of RVVSignatureTable. |
||
| 486 | uint16_t OverloadedSuffixIndex; |
||
| 487 | |||
| 488 | // Length of the prototype. |
||
| 489 | uint8_t PrototypeLength; |
||
| 490 | |||
| 491 | // Length of intrinsic name suffix. |
||
| 492 | uint8_t SuffixLength; |
||
| 493 | |||
| 494 | // Length of overloaded intrinsic suffix. |
||
| 495 | uint8_t OverloadedSuffixSize; |
||
| 496 | |||
| 497 | // Required target features for this intrinsic. |
||
| 498 | uint8_t RequiredExtensions; |
||
| 499 | |||
| 500 | // Supported type, mask of BasicType. |
||
| 501 | uint8_t TypeRangeMask; |
||
| 502 | |||
| 503 | // Supported LMUL. |
||
| 504 | uint8_t Log2LMULMask; |
||
| 505 | |||
| 506 | // Number of fields, greater than 1 if it's segment load/store. |
||
| 507 | uint8_t NF; |
||
| 508 | |||
| 509 | bool HasMasked : 1; |
||
| 510 | bool HasVL : 1; |
||
| 511 | bool HasMaskedOffOperand : 1; |
||
| 512 | bool HasTailPolicy : 1; |
||
| 513 | bool HasMaskPolicy : 1; |
||
| 514 | uint8_t UnMaskedPolicyScheme : 2; |
||
| 515 | uint8_t MaskedPolicyScheme : 2; |
||
| 516 | }; |
||
| 517 | |||
| 518 | llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, |
||
| 519 | const RVVIntrinsicRecord &RVVInstrRecord); |
||
| 520 | |||
| 521 | LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); |
||
| 522 | } // end namespace RISCV |
||
| 523 | |||
| 524 | } // end namespace clang |
||
| 525 | |||
| 526 | #endif // CLANG_SUPPORT_RISCVVINTRINSICUTILS_H |