File indexing completed on 2026-05-10 08:37:10
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef CLANG_SUPPORT_RISCVVINTRINSICUTILS_H
0010 #define CLANG_SUPPORT_RISCVVINTRINSICUTILS_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/BitmaskEnum.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include <cstdint>
0017 #include <optional>
0018 #include <set>
0019 #include <string>
0020 #include <unordered_map>
0021 #include <vector>
0022
0023 namespace llvm {
0024 class raw_ostream;
0025 }
0026
0027 namespace clang {
0028 namespace RISCV {
0029
0030 using VScaleVal = std::optional<unsigned>;
0031
0032
0033 enum class VectorTypeModifier : uint8_t {
0034 NoModifier,
0035 Widening2XVector,
0036 Widening4XVector,
0037 Widening8XVector,
0038 MaskVector,
0039 Log2EEW3,
0040 Log2EEW4,
0041 Log2EEW5,
0042 Log2EEW6,
0043 FixedSEW8,
0044 FixedSEW16,
0045 FixedSEW32,
0046 FixedSEW64,
0047 LFixedLog2LMULN3,
0048 LFixedLog2LMULN2,
0049 LFixedLog2LMULN1,
0050 LFixedLog2LMUL0,
0051 LFixedLog2LMUL1,
0052 LFixedLog2LMUL2,
0053 LFixedLog2LMUL3,
0054 SFixedLog2LMULN3,
0055 SFixedLog2LMULN2,
0056 SFixedLog2LMULN1,
0057 SFixedLog2LMUL0,
0058 SFixedLog2LMUL1,
0059 SFixedLog2LMUL2,
0060 SFixedLog2LMUL3,
0061 SEFixedLog2LMULN3,
0062 SEFixedLog2LMULN2,
0063 SEFixedLog2LMULN1,
0064 SEFixedLog2LMUL0,
0065 SEFixedLog2LMUL1,
0066 SEFixedLog2LMUL2,
0067 SEFixedLog2LMUL3,
0068 Tuple2,
0069 Tuple3,
0070 Tuple4,
0071 Tuple5,
0072 Tuple6,
0073 Tuple7,
0074 Tuple8,
0075 };
0076
0077
0078
0079 enum class BaseTypeModifier : uint8_t {
0080 Invalid,
0081 Scalar,
0082 Vector,
0083 Void,
0084 SizeT,
0085 Ptrdiff,
0086 UnsignedLong,
0087 SignedLong,
0088 Float32
0089 };
0090
0091
0092 enum class TypeModifier : uint8_t {
0093 NoModifier = 0,
0094 Pointer = 1 << 0,
0095 Const = 1 << 1,
0096 Immediate = 1 << 2,
0097 UnsignedInteger = 1 << 3,
0098 SignedInteger = 1 << 4,
0099 Float = 1 << 5,
0100 BFloat = 1 << 6,
0101
0102
0103
0104
0105
0106 LMUL1 = 1 << 7,
0107 MaxOffset = 7,
0108 LLVM_MARK_AS_BITMASK_ENUM(LMUL1),
0109 };
0110
0111 class Policy {
0112 public:
0113 enum PolicyType {
0114 Undisturbed,
0115 Agnostic,
0116 };
0117
0118 private:
0119
0120
0121 const PolicyType TailPolicy = Agnostic;
0122 const PolicyType MaskPolicy = Agnostic;
0123
0124 public:
0125 Policy() = default;
0126 Policy(PolicyType TailPolicy) : TailPolicy(TailPolicy) {}
0127 Policy(PolicyType TailPolicy, PolicyType MaskPolicy)
0128 : TailPolicy(TailPolicy), MaskPolicy(MaskPolicy) {}
0129
0130 bool isTAMAPolicy() const {
0131 return TailPolicy == Agnostic && MaskPolicy == Agnostic;
0132 }
0133
0134 bool isTAMUPolicy() const {
0135 return TailPolicy == Agnostic && MaskPolicy == Undisturbed;
0136 }
0137
0138 bool isTUMAPolicy() const {
0139 return TailPolicy == Undisturbed && MaskPolicy == Agnostic;
0140 }
0141
0142 bool isTUMUPolicy() const {
0143 return TailPolicy == Undisturbed && MaskPolicy == Undisturbed;
0144 }
0145
0146 bool isTAPolicy() const { return TailPolicy == Agnostic; }
0147
0148 bool isTUPolicy() const { return TailPolicy == Undisturbed; }
0149
0150 bool isMAPolicy() const { return MaskPolicy == Agnostic; }
0151
0152 bool isMUPolicy() const { return MaskPolicy == Undisturbed; }
0153
0154 bool operator==(const Policy &Other) const {
0155 return TailPolicy == Other.TailPolicy && MaskPolicy == Other.MaskPolicy;
0156 }
0157
0158 bool operator!=(const Policy &Other) const { return !(*this == Other); }
0159
0160 bool operator<(const Policy &Other) const {
0161
0162 if (MaskPolicy != Other.MaskPolicy)
0163 return Other.MaskPolicy < MaskPolicy;
0164 return TailPolicy < Other.TailPolicy;
0165 }
0166 };
0167
0168
0169
0170 struct PrototypeDescriptor {
0171 constexpr PrototypeDescriptor() = default;
0172 constexpr PrototypeDescriptor(
0173 BaseTypeModifier PT,
0174 VectorTypeModifier VTM = VectorTypeModifier::NoModifier,
0175 TypeModifier TM = TypeModifier::NoModifier)
0176 : PT(static_cast<uint8_t>(PT)), VTM(static_cast<uint8_t>(VTM)),
0177 TM(static_cast<uint8_t>(TM)) {}
0178 constexpr PrototypeDescriptor(uint8_t PT, uint8_t VTM, uint8_t TM)
0179 : PT(PT), VTM(VTM), TM(TM) {}
0180
0181 uint8_t PT = static_cast<uint8_t>(BaseTypeModifier::Invalid);
0182 uint8_t VTM = static_cast<uint8_t>(VectorTypeModifier::NoModifier);
0183 uint8_t TM = static_cast<uint8_t>(TypeModifier::NoModifier);
0184
0185 bool operator!=(const PrototypeDescriptor &PD) const {
0186 return !(*this == PD);
0187 }
0188 bool operator==(const PrototypeDescriptor &PD) const {
0189 return PD.PT == PT && PD.VTM == VTM && PD.TM == TM;
0190 }
0191 bool operator<(const PrototypeDescriptor &PD) const {
0192 return std::tie(PT, VTM, TM) < std::tie(PD.PT, PD.VTM, PD.TM);
0193 }
0194 static const PrototypeDescriptor Mask;
0195 static const PrototypeDescriptor Vector;
0196 static const PrototypeDescriptor VL;
0197 static std::optional<PrototypeDescriptor>
0198 parsePrototypeDescriptor(llvm::StringRef PrototypeStr);
0199 };
0200
0201 llvm::SmallVector<PrototypeDescriptor>
0202 parsePrototypes(llvm::StringRef Prototypes);
0203
0204
0205 enum class BasicType : uint8_t {
0206 Unknown = 0,
0207 Int8 = 1 << 0,
0208 Int16 = 1 << 1,
0209 Int32 = 1 << 2,
0210 Int64 = 1 << 3,
0211 BFloat16 = 1 << 4,
0212 Float16 = 1 << 5,
0213 Float32 = 1 << 6,
0214 Float64 = 1 << 7,
0215 MaxOffset = 7,
0216 LLVM_MARK_AS_BITMASK_ENUM(Float64),
0217 };
0218
0219
0220 enum ScalarTypeKind : uint8_t {
0221 Void,
0222 Size_t,
0223 Ptrdiff_t,
0224 UnsignedLong,
0225 SignedLong,
0226 Boolean,
0227 SignedInteger,
0228 UnsignedInteger,
0229 Float,
0230 BFloat,
0231 Invalid,
0232 Undefined,
0233 };
0234
0235
0236 struct LMULType {
0237 int Log2LMUL;
0238 LMULType(int Log2LMUL);
0239
0240 std::string str() const;
0241 std::optional<unsigned> getScale(unsigned ElementBitwidth) const;
0242 void MulLog2LMUL(int Log2LMUL);
0243 };
0244
0245 class RVVType;
0246 using RVVTypePtr = RVVType *;
0247 using RVVTypes = std::vector<RVVTypePtr>;
0248 class RVVTypeCache;
0249
0250
0251 class RVVType {
0252 friend class RVVTypeCache;
0253
0254 BasicType BT;
0255 ScalarTypeKind ScalarType = Undefined;
0256 LMULType LMUL;
0257 bool IsPointer = false;
0258
0259 bool IsImmediate = false;
0260
0261 bool IsConstant = false;
0262 unsigned ElementBitwidth = 0;
0263 VScaleVal Scale = 0;
0264 bool Valid;
0265 bool IsTuple = false;
0266 unsigned NF = 0;
0267
0268 std::string BuiltinStr;
0269 std::string ClangBuiltinStr;
0270 std::string Str;
0271 std::string ShortStr;
0272
0273 enum class FixedLMULType { LargerThan, SmallerThan, SmallerOrEqual };
0274
0275 RVVType(BasicType BT, int Log2LMUL, const PrototypeDescriptor &Profile);
0276
0277 public:
0278
0279
0280 const std::string &getBuiltinStr() const { return BuiltinStr; }
0281
0282
0283
0284 const std::string &getClangBuiltinStr() const { return ClangBuiltinStr; }
0285
0286
0287
0288 const std::string &getTypeStr() const { return Str; }
0289
0290
0291 const std::string &getShortStr() {
0292
0293
0294 if (ShortStr.empty())
0295 initShortStr();
0296 return ShortStr;
0297 }
0298
0299 bool isValid() const { return Valid; }
0300 bool isScalar() const { return Scale && *Scale == 0; }
0301 bool isVector() const { return Scale && *Scale != 0; }
0302 bool isVector(unsigned Width) const {
0303 return isVector() && ElementBitwidth == Width;
0304 }
0305 bool isFloat() const { return ScalarType == ScalarTypeKind::Float; }
0306 bool isBFloat() const { return ScalarType == ScalarTypeKind::BFloat; }
0307 bool isSignedInteger() const {
0308 return ScalarType == ScalarTypeKind::SignedInteger;
0309 }
0310 bool isFloatVector(unsigned Width) const {
0311 return isVector() && isFloat() && ElementBitwidth == Width;
0312 }
0313 bool isFloat(unsigned Width) const {
0314 return isFloat() && ElementBitwidth == Width;
0315 }
0316 bool isConstant() const { return IsConstant; }
0317 bool isPointer() const { return IsPointer; }
0318 bool isTuple() const { return IsTuple; }
0319 unsigned getElementBitwidth() const { return ElementBitwidth; }
0320
0321 ScalarTypeKind getScalarType() const { return ScalarType; }
0322 VScaleVal getScale() const { return Scale; }
0323 unsigned getNF() const {
0324 assert(NF > 1 && NF <= 8 && "Only legal NF should be fetched");
0325 return NF;
0326 }
0327
0328 private:
0329
0330 bool verifyType() const;
0331
0332
0333 void applyBasicType();
0334
0335
0336
0337 void applyModifier(const PrototypeDescriptor &prototype);
0338
0339 void applyLog2EEW(unsigned Log2EEW);
0340 void applyFixedSEW(unsigned NewSEW);
0341 void applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type);
0342
0343
0344 void initBuiltinStr();
0345
0346 void initClangBuiltinStr();
0347
0348 void initTypeStr();
0349
0350 void initShortStr();
0351 };
0352
0353
0354
0355 class RVVTypeCache {
0356 private:
0357 std::unordered_map<uint64_t, RVVType> LegalTypes;
0358 std::set<uint64_t> IllegalTypes;
0359
0360 public:
0361
0362
0363
0364
0365 std::optional<RVVTypes>
0366 computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
0367 llvm::ArrayRef<PrototypeDescriptor> Prototype);
0368 std::optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL,
0369 PrototypeDescriptor Proto);
0370 };
0371
0372 enum PolicyScheme : uint8_t {
0373 SchemeNone,
0374
0375 HasPassthruOperand,
0376 HasPolicyOperand,
0377 };
0378
0379
0380
0381
0382 class RVVIntrinsic {
0383
0384 private:
0385 std::string BuiltinName;
0386 std::string Name;
0387 std::string OverloadedName;
0388 std::string IRName;
0389 bool IsMasked;
0390 bool HasMaskedOffOperand;
0391 bool HasVL;
0392 PolicyScheme Scheme;
0393 bool SupportOverloading;
0394 bool HasBuiltinAlias;
0395 std::string ManualCodegen;
0396 RVVTypePtr OutputType;
0397 RVVTypes InputTypes;
0398
0399
0400 std::vector<int64_t> IntrinsicTypes;
0401 unsigned NF = 1;
0402 Policy PolicyAttrs;
0403
0404 public:
0405 RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix,
0406 llvm::StringRef OverloadedName, llvm::StringRef OverloadedSuffix,
0407 llvm::StringRef IRName, bool IsMasked, bool HasMaskedOffOperand,
0408 bool HasVL, PolicyScheme Scheme, bool SupportOverloading,
0409 bool HasBuiltinAlias, llvm::StringRef ManualCodegen,
0410 const RVVTypes &Types,
0411 const std::vector<int64_t> &IntrinsicTypes,
0412 unsigned NF, Policy PolicyAttrs, bool HasFRMRoundModeOp);
0413 ~RVVIntrinsic() = default;
0414
0415 RVVTypePtr getOutputType() const { return OutputType; }
0416 const RVVTypes &getInputTypes() const { return InputTypes; }
0417 llvm::StringRef getBuiltinName() const { return BuiltinName; }
0418 bool hasMaskedOffOperand() const { return HasMaskedOffOperand; }
0419 bool hasVL() const { return HasVL; }
0420 bool hasPolicy() const { return Scheme != PolicyScheme::SchemeNone; }
0421 bool hasPassthruOperand() const {
0422 return Scheme == PolicyScheme::HasPassthruOperand;
0423 }
0424 bool hasPolicyOperand() const {
0425 return Scheme == PolicyScheme::HasPolicyOperand;
0426 }
0427 bool supportOverloading() const { return SupportOverloading; }
0428 bool hasBuiltinAlias() const { return HasBuiltinAlias; }
0429 bool hasManualCodegen() const { return !ManualCodegen.empty(); }
0430 bool isMasked() const { return IsMasked; }
0431 llvm::StringRef getOverloadedName() const { return OverloadedName; }
0432 llvm::StringRef getIRName() const { return IRName; }
0433 llvm::StringRef getManualCodegen() const { return ManualCodegen; }
0434 PolicyScheme getPolicyScheme() const { return Scheme; }
0435 unsigned getNF() const { return NF; }
0436 const std::vector<int64_t> &getIntrinsicTypes() const {
0437 return IntrinsicTypes;
0438 }
0439 Policy getPolicyAttrs() const {
0440 return PolicyAttrs;
0441 }
0442 unsigned getPolicyAttrsBits() const {
0443
0444
0445
0446
0447
0448 if (PolicyAttrs.isTUMAPolicy())
0449 return 2;
0450 if (PolicyAttrs.isTAMAPolicy())
0451 return 3;
0452 if (PolicyAttrs.isTUMUPolicy())
0453 return 0;
0454 if (PolicyAttrs.isTAMUPolicy())
0455 return 1;
0456
0457 llvm_unreachable("unsupport policy");
0458 return 0;
0459 }
0460
0461
0462 std::string getBuiltinTypeStr() const;
0463
0464 static std::string
0465 getSuffixStr(RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
0466 llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors);
0467
0468 static llvm::SmallVector<PrototypeDescriptor>
0469 computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype,
0470 bool IsMasked, bool HasMaskedOffOperand, bool HasVL,
0471 unsigned NF, PolicyScheme DefaultScheme,
0472 Policy PolicyAttrs, bool IsTuple);
0473
0474 static llvm::SmallVector<Policy> getSupportedUnMaskedPolicies();
0475 static llvm::SmallVector<Policy>
0476 getSupportedMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy);
0477
0478 static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
0479 std::string &Name, std::string &BuiltinName,
0480 std::string &OverloadedName,
0481 Policy &PolicyAttrs, bool HasFRMRoundModeOp);
0482 };
0483
0484
0485
0486 enum RVVRequire : uint32_t {
0487 RVV_REQ_None = 0,
0488 RVV_REQ_RV64 = 1 << 0,
0489 RVV_REQ_Zvfhmin = 1 << 1,
0490 RVV_REQ_Xsfvcp = 1 << 2,
0491 RVV_REQ_Xsfvfnrclipxfqf = 1 << 3,
0492 RVV_REQ_Xsfvfwmaccqqq = 1 << 4,
0493 RVV_REQ_Xsfvqmaccdod = 1 << 5,
0494 RVV_REQ_Xsfvqmaccqoq = 1 << 6,
0495 RVV_REQ_Zvbb = 1 << 7,
0496 RVV_REQ_Zvbc = 1 << 8,
0497 RVV_REQ_Zvkb = 1 << 9,
0498 RVV_REQ_Zvkg = 1 << 10,
0499 RVV_REQ_Zvkned = 1 << 11,
0500 RVV_REQ_Zvknha = 1 << 12,
0501 RVV_REQ_Zvknhb = 1 << 13,
0502 RVV_REQ_Zvksed = 1 << 14,
0503 RVV_REQ_Zvksh = 1 << 15,
0504 RVV_REQ_Zvfbfwma = 1 << 16,
0505 RVV_REQ_Zvfbfmin = 1 << 17,
0506 RVV_REQ_Zvfh = 1 << 18,
0507 RVV_REQ_Experimental = 1 << 19,
0508
0509 LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_Experimental)
0510 };
0511
0512
0513
0514 struct RVVIntrinsicRecord {
0515
0516 const char *Name;
0517
0518
0519
0520 const char *OverloadedName;
0521
0522
0523 uint16_t PrototypeIndex;
0524
0525
0526 uint16_t SuffixIndex;
0527
0528
0529 uint16_t OverloadedSuffixIndex;
0530
0531
0532 uint8_t PrototypeLength;
0533
0534
0535 uint8_t SuffixLength;
0536
0537
0538 uint8_t OverloadedSuffixSize;
0539
0540
0541 uint32_t RequiredExtensions;
0542
0543
0544 uint8_t TypeRangeMask;
0545
0546
0547 uint8_t Log2LMULMask;
0548
0549
0550 uint8_t NF;
0551
0552 bool HasMasked : 1;
0553 bool HasVL : 1;
0554 bool HasMaskedOffOperand : 1;
0555 bool HasTailPolicy : 1;
0556 bool HasMaskPolicy : 1;
0557 bool HasFRMRoundModeOp : 1;
0558 bool IsTuple : 1;
0559 LLVM_PREFERRED_TYPE(PolicyScheme)
0560 uint8_t UnMaskedPolicyScheme : 2;
0561 LLVM_PREFERRED_TYPE(PolicyScheme)
0562 uint8_t MaskedPolicyScheme : 2;
0563 };
0564
0565 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
0566 const RVVIntrinsicRecord &RVVInstrRecord);
0567
0568 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
0569 }
0570
0571 }
0572
0573 #endif