1 //===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//
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
7 //===----------------------------------------------------------------------===//
9 // This tablegen backend is responsible for emitting riscv_vector.h which
10 // includes a declaration and definition of each intrinsic functions specified
11 // in https://github.com/riscv/rvv-intrinsic-doc.
13 // See also the documentation in include/clang/Basic/riscv_vector.td.
15 //===----------------------------------------------------------------------===//
17 #include "clang/Support/RISCVVIntrinsicUtils.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/SmallSet.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringSet.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Twine.h"
25 #include "llvm/TableGen/Error.h"
26 #include "llvm/TableGen/Record.h"
31 using namespace clang::RISCV
;
35 // Intrinsic name, e.g. vadd_vv
38 // Overloaded intrinsic name, could be empty if can be computed from Name
40 std::string OverloadedName
;
42 // Supported type, mask of BasicType.
43 unsigned TypeRangeMask
;
46 unsigned Log2LMULMask
;
48 // Required extensions for this intrinsic.
49 unsigned RequiredExtensions
;
51 // Prototype for this intrinsic.
52 SmallVector
<PrototypeDescriptor
> Prototype
;
54 // Suffix of intrinsic name.
55 SmallVector
<PrototypeDescriptor
> Suffix
;
57 // Suffix of overloaded intrinsic name.
58 SmallVector
<PrototypeDescriptor
> OverloadedSuffix
;
60 // Number of field, large than 1 if it's segment load/store.
65 bool HasMaskedOffOperand
:1;
66 bool HasTailPolicy
: 1;
67 bool HasMaskPolicy
: 1;
68 bool HasFRMRoundModeOp
: 1;
70 uint8_t UnMaskedPolicyScheme
: 2;
71 uint8_t MaskedPolicyScheme
: 2;
74 // Compressed function signature table.
75 class SemaSignatureTable
{
77 std::vector
<PrototypeDescriptor
> SignatureTable
;
79 void insert(ArrayRef
<PrototypeDescriptor
> Signature
);
82 static constexpr unsigned INVALID_INDEX
= ~0U;
84 // Create compressed signature table from SemaRecords.
85 void init(ArrayRef
<SemaRecord
> SemaRecords
);
87 // Query the Signature, return INVALID_INDEX if not found.
88 unsigned getIndex(ArrayRef
<PrototypeDescriptor
> Signature
);
90 /// Print signature table in RVVHeader Record to \p OS
91 void print(raw_ostream
&OS
);
96 RecordKeeper
&Records
;
97 RVVTypeCache TypeCache
;
100 RVVEmitter(RecordKeeper
&R
) : Records(R
) {}
102 /// Emit riscv_vector.h
103 void createHeader(raw_ostream
&o
);
105 /// Emit all the __builtin prototypes and code needed by Sema.
106 void createBuiltins(raw_ostream
&o
);
108 /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
109 void createCodeGen(raw_ostream
&o
);
111 /// Emit all the information needed by SemaRISCVVectorLookup.cpp.
112 /// We've large number of intrinsic function for RVV, creating a customized
113 /// could speed up the compilation time.
114 void createSema(raw_ostream
&o
);
117 /// Create all intrinsics and add them to \p Out and SemaRecords.
118 void createRVVIntrinsics(std::vector
<std::unique_ptr
<RVVIntrinsic
>> &Out
,
119 std::vector
<SemaRecord
> *SemaRecords
= nullptr);
120 /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
121 void createRVVIntrinsicRecords(std::vector
<RVVIntrinsicRecord
> &Out
,
122 SemaSignatureTable
&SST
,
123 ArrayRef
<SemaRecord
> SemaRecords
);
125 /// Print HeaderCode in RVVHeader Record to \p Out
126 void printHeaderCode(raw_ostream
&OS
);
131 static BasicType
ParseBasicType(char c
) {
134 return BasicType::Int8
;
137 return BasicType::Int16
;
140 return BasicType::Int32
;
143 return BasicType::Int64
;
146 return BasicType::Float16
;
149 return BasicType::Float32
;
152 return BasicType::Float64
;
155 return BasicType::BFloat16
;
158 return BasicType::Unknown
;
162 static VectorTypeModifier
getTupleVTM(unsigned NF
) {
163 assert(2 <= NF
&& NF
<= 8 && "2 <= NF <= 8");
164 return static_cast<VectorTypeModifier
>(
165 static_cast<uint8_t>(VectorTypeModifier::Tuple2
) + (NF
- 2));
168 void emitCodeGenSwitchBody(const RVVIntrinsic
*RVVI
, raw_ostream
&OS
) {
169 if (!RVVI
->getIRName().empty())
170 OS
<< " ID = Intrinsic::riscv_" + RVVI
->getIRName() + ";\n";
171 if (RVVI
->getNF() >= 2)
172 OS
<< " NF = " + utostr(RVVI
->getNF()) + ";\n";
174 OS
<< " PolicyAttrs = " << RVVI
->getPolicyAttrsBits() << ";\n";
176 if (RVVI
->hasManualCodegen()) {
177 OS
<< "IsMasked = " << (RVVI
->isMasked() ? "true" : "false") << ";\n";
178 OS
<< RVVI
->getManualCodegen();
183 // Cast pointer operand of vector load intrinsic.
184 for (const auto &I
: enumerate(RVVI
->getInputTypes())) {
185 if (I
.value()->isPointer()) {
186 assert(RVVI
->getIntrinsicTypes().front() == -1 &&
187 "RVVI should be vector load intrinsic.");
188 OS
<< " Ops[" << I
.index() << "] = Builder.CreateBitCast(Ops[";
189 OS
<< I
.index() << "], ResultType->getPointerTo());\n";
193 if (RVVI
->isMasked()) {
195 OS
<< " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
196 if (RVVI
->hasPolicyOperand())
197 OS
<< " Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
199 if (RVVI
->hasMaskedOffOperand() && RVVI
->getPolicyAttrs().isTAMAPolicy())
200 OS
<< " Ops.insert(Ops.begin(), "
201 "llvm::PoisonValue::get(ResultType));\n";
202 // Masked reduction cases.
203 if (!RVVI
->hasMaskedOffOperand() && RVVI
->hasPassthruOperand() &&
204 RVVI
->getPolicyAttrs().isTAMAPolicy())
205 OS
<< " Ops.insert(Ops.begin(), "
206 "llvm::PoisonValue::get(ResultType));\n";
208 OS
<< " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
211 if (RVVI
->hasPolicyOperand())
212 OS
<< " Ops.push_back(ConstantInt::get(Ops.back()->getType(), "
214 else if (RVVI
->hasPassthruOperand() && RVVI
->getPolicyAttrs().isTAPolicy())
215 OS
<< " Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));\n";
218 OS
<< " IntrinsicTypes = {";
220 for (const auto &Idx
: RVVI
->getIntrinsicTypes()) {
222 OS
<< LS
<< "ResultType";
224 OS
<< LS
<< "Ops[" << Idx
<< "]->getType()";
227 // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
228 // always last operand.
230 OS
<< ", Ops.back()->getType()";
235 //===----------------------------------------------------------------------===//
236 // SemaSignatureTable implementation
237 //===----------------------------------------------------------------------===//
238 void SemaSignatureTable::init(ArrayRef
<SemaRecord
> SemaRecords
) {
239 // Sort signature entries by length, let longer signature insert first, to
240 // make it more possible to reuse table entries, that can reduce ~10% table
243 bool operator()(const SmallVector
<PrototypeDescriptor
> &A
,
244 const SmallVector
<PrototypeDescriptor
> &B
) const {
245 if (A
.size() != B
.size())
246 return A
.size() > B
.size();
248 size_t Len
= A
.size();
249 for (size_t i
= 0; i
< Len
; ++i
) {
258 std::set
<SmallVector
<PrototypeDescriptor
>, Compare
> Signatures
;
259 auto InsertToSignatureSet
=
260 [&](const SmallVector
<PrototypeDescriptor
> &Signature
) {
261 if (Signature
.empty())
264 Signatures
.insert(Signature
);
267 assert(!SemaRecords
.empty());
269 for (const SemaRecord
&SR
: SemaRecords
) {
270 InsertToSignatureSet(SR
.Prototype
);
271 InsertToSignatureSet(SR
.Suffix
);
272 InsertToSignatureSet(SR
.OverloadedSuffix
);
275 for (auto &Sig
: Signatures
)
279 void SemaSignatureTable::insert(ArrayRef
<PrototypeDescriptor
> Signature
) {
280 if (getIndex(Signature
) != INVALID_INDEX
)
283 // Insert Signature into SignatureTable if not found in the table.
284 SignatureTable
.insert(SignatureTable
.begin(), Signature
.begin(),
288 unsigned SemaSignatureTable::getIndex(ArrayRef
<PrototypeDescriptor
> Signature
) {
289 // Empty signature could be point into any index since there is length
290 // field when we use, so just always point it to 0.
291 if (Signature
.empty())
294 // Checking Signature already in table or not.
295 if (Signature
.size() <= SignatureTable
.size()) {
296 size_t Bound
= SignatureTable
.size() - Signature
.size() + 1;
297 for (size_t Index
= 0; Index
< Bound
; ++Index
) {
298 if (equal(Signature
.begin(), Signature
.end(),
299 SignatureTable
.begin() + Index
))
304 return INVALID_INDEX
;
307 void SemaSignatureTable::print(raw_ostream
&OS
) {
308 for (const auto &Sig
: SignatureTable
)
309 OS
<< "PrototypeDescriptor(" << static_cast<int>(Sig
.PT
) << ", "
310 << static_cast<int>(Sig
.VTM
) << ", " << static_cast<int>(Sig
.TM
)
314 //===----------------------------------------------------------------------===//
315 // RVVEmitter implementation
316 //===----------------------------------------------------------------------===//
317 void RVVEmitter::createHeader(raw_ostream
&OS
) {
319 OS
<< "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
320 "-------------------===\n"
323 " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
325 " * See https://llvm.org/LICENSE.txt for license information.\n"
326 " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
328 " *===-----------------------------------------------------------------"
332 OS
<< "#ifndef __RISCV_VECTOR_H\n";
333 OS
<< "#define __RISCV_VECTOR_H\n\n";
335 OS
<< "#include <stdint.h>\n";
336 OS
<< "#include <stddef.h>\n\n";
338 OS
<< "#ifndef __riscv_vector\n";
339 OS
<< "#error \"Vector intrinsics require the vector extension.\"\n";
342 OS
<< "#ifdef __cplusplus\n";
343 OS
<< "extern \"C\" {\n";
346 OS
<< "#pragma clang riscv intrinsic vector\n\n";
350 auto printType
= [&](auto T
) {
351 OS
<< "typedef " << T
->getClangBuiltinStr() << " " << T
->getTypeStr()
355 constexpr int Log2LMULs
[] = {-3, -2, -1, 0, 1, 2, 3};
356 // Print RVV boolean types.
357 for (int Log2LMUL
: Log2LMULs
) {
358 auto T
= TypeCache
.computeType(BasicType::Int8
, Log2LMUL
,
359 PrototypeDescriptor::Mask
);
363 // Print RVV int/float types.
364 for (char I
: StringRef("csil")) {
365 BasicType BT
= ParseBasicType(I
);
366 for (int Log2LMUL
: Log2LMULs
) {
367 auto T
= TypeCache
.computeType(BT
, Log2LMUL
, PrototypeDescriptor::Vector
);
370 auto UT
= TypeCache
.computeType(
372 PrototypeDescriptor(BaseTypeModifier::Vector
,
373 VectorTypeModifier::NoModifier
,
374 TypeModifier::UnsignedInteger
));
377 for (int NF
= 2; NF
<= 8; ++NF
) {
378 auto TupleT
= TypeCache
.computeType(
380 PrototypeDescriptor(BaseTypeModifier::Vector
, getTupleVTM(NF
),
381 TypeModifier::SignedInteger
));
382 auto TupleUT
= TypeCache
.computeType(
384 PrototypeDescriptor(BaseTypeModifier::Vector
, getTupleVTM(NF
),
385 TypeModifier::UnsignedInteger
));
394 for (BasicType BT
: {BasicType::Float16
, BasicType::Float32
,
395 BasicType::Float64
, BasicType::BFloat16
}) {
396 for (int Log2LMUL
: Log2LMULs
) {
397 auto T
= TypeCache
.computeType(BT
, Log2LMUL
, PrototypeDescriptor::Vector
);
400 for (int NF
= 2; NF
<= 8; ++NF
) {
401 auto TupleT
= TypeCache
.computeType(
403 PrototypeDescriptor(BaseTypeModifier::Vector
, getTupleVTM(NF
),
404 (BT
== BasicType::BFloat16
405 ? TypeModifier::BFloat
406 : TypeModifier::Float
)));
413 OS
<< "#define __riscv_v_intrinsic_overloading 1\n";
415 OS
<< "\n#ifdef __cplusplus\n";
417 OS
<< "#endif // __cplusplus\n";
418 OS
<< "#endif // __RISCV_VECTOR_H\n";
421 void RVVEmitter::createBuiltins(raw_ostream
&OS
) {
422 std::vector
<std::unique_ptr
<RVVIntrinsic
>> Defs
;
423 createRVVIntrinsics(Defs
);
425 // Map to keep track of which builtin names have already been emitted.
426 StringMap
<RVVIntrinsic
*> BuiltinMap
;
428 OS
<< "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
429 OS
<< "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
430 "ATTRS, \"zve32x\")\n";
432 for (auto &Def
: Defs
) {
434 BuiltinMap
.insert(std::make_pair(Def
->getBuiltinName(), Def
.get()));
436 // Verf that this would have produced the same builtin definition.
437 if (P
.first
->second
->hasBuiltinAlias() != Def
->hasBuiltinAlias())
438 PrintFatalError("Builtin with same name has different hasAutoDef");
439 else if (!Def
->hasBuiltinAlias() &&
440 P
.first
->second
->getBuiltinTypeStr() != Def
->getBuiltinTypeStr())
441 PrintFatalError("Builtin with same name has different type string");
444 OS
<< "RISCVV_BUILTIN(__builtin_rvv_" << Def
->getBuiltinName() << ",\"";
445 if (!Def
->hasBuiltinAlias())
446 OS
<< Def
->getBuiltinTypeStr();
447 OS
<< "\", \"n\")\n";
449 OS
<< "#undef RISCVV_BUILTIN\n";
452 void RVVEmitter::createCodeGen(raw_ostream
&OS
) {
453 std::vector
<std::unique_ptr
<RVVIntrinsic
>> Defs
;
454 createRVVIntrinsics(Defs
);
455 // IR name could be empty, use the stable sort preserves the relative order.
456 llvm::stable_sort(Defs
, [](const std::unique_ptr
<RVVIntrinsic
> &A
,
457 const std::unique_ptr
<RVVIntrinsic
> &B
) {
458 if (A
->getIRName() == B
->getIRName())
459 return (A
->getPolicyAttrs() < B
->getPolicyAttrs());
460 return (A
->getIRName() < B
->getIRName());
463 // Map to keep track of which builtin names have already been emitted.
464 StringMap
<RVVIntrinsic
*> BuiltinMap
;
466 // Print switch body when the ir name, ManualCodegen or policy changes from
467 // previous iteration.
468 RVVIntrinsic
*PrevDef
= Defs
.begin()->get();
469 for (auto &Def
: Defs
) {
470 StringRef CurIRName
= Def
->getIRName();
471 if (CurIRName
!= PrevDef
->getIRName() ||
472 (Def
->getManualCodegen() != PrevDef
->getManualCodegen()) ||
473 (Def
->getPolicyAttrs() != PrevDef
->getPolicyAttrs())) {
474 emitCodeGenSwitchBody(PrevDef
, OS
);
479 BuiltinMap
.insert(std::make_pair(Def
->getBuiltinName(), Def
.get()));
481 OS
<< "case RISCVVector::BI__builtin_rvv_" << Def
->getBuiltinName()
486 if (P
.first
->second
->getIRName() != Def
->getIRName())
487 PrintFatalError("Builtin with same name has different IRName");
488 else if (P
.first
->second
->getManualCodegen() != Def
->getManualCodegen())
489 PrintFatalError("Builtin with same name has different ManualCodegen");
490 else if (P
.first
->second
->isMasked() != Def
->isMasked())
491 PrintFatalError("Builtin with same name has different isMasked");
492 else if (P
.first
->second
->hasVL() != Def
->hasVL())
493 PrintFatalError("Builtin with same name has different hasVL");
494 else if (P
.first
->second
->getPolicyScheme() != Def
->getPolicyScheme())
495 PrintFatalError("Builtin with same name has different getPolicyScheme");
496 else if (P
.first
->second
->getIntrinsicTypes() != Def
->getIntrinsicTypes())
497 PrintFatalError("Builtin with same name has different IntrinsicTypes");
499 emitCodeGenSwitchBody(Defs
.back().get(), OS
);
503 void RVVEmitter::createRVVIntrinsics(
504 std::vector
<std::unique_ptr
<RVVIntrinsic
>> &Out
,
505 std::vector
<SemaRecord
> *SemaRecords
) {
506 std::vector
<Record
*> RV
= Records
.getAllDerivedDefinitions("RVVBuiltin");
508 StringRef Name
= R
->getValueAsString("Name");
509 StringRef SuffixProto
= R
->getValueAsString("Suffix");
510 StringRef OverloadedName
= R
->getValueAsString("OverloadedName");
511 StringRef OverloadedSuffixProto
= R
->getValueAsString("OverloadedSuffix");
512 StringRef Prototypes
= R
->getValueAsString("Prototype");
513 StringRef TypeRange
= R
->getValueAsString("TypeRange");
514 bool HasMasked
= R
->getValueAsBit("HasMasked");
515 bool HasMaskedOffOperand
= R
->getValueAsBit("HasMaskedOffOperand");
516 bool HasVL
= R
->getValueAsBit("HasVL");
517 Record
*MPSRecord
= R
->getValueAsDef("MaskedPolicyScheme");
518 auto MaskedPolicyScheme
=
519 static_cast<PolicyScheme
>(MPSRecord
->getValueAsInt("Value"));
520 Record
*UMPSRecord
= R
->getValueAsDef("UnMaskedPolicyScheme");
521 auto UnMaskedPolicyScheme
=
522 static_cast<PolicyScheme
>(UMPSRecord
->getValueAsInt("Value"));
523 std::vector
<int64_t> Log2LMULList
= R
->getValueAsListOfInts("Log2LMUL");
524 bool HasTailPolicy
= R
->getValueAsBit("HasTailPolicy");
525 bool HasMaskPolicy
= R
->getValueAsBit("HasMaskPolicy");
526 bool SupportOverloading
= R
->getValueAsBit("SupportOverloading");
527 bool HasBuiltinAlias
= R
->getValueAsBit("HasBuiltinAlias");
528 StringRef ManualCodegen
= R
->getValueAsString("ManualCodegen");
529 std::vector
<int64_t> IntrinsicTypes
=
530 R
->getValueAsListOfInts("IntrinsicTypes");
531 std::vector
<StringRef
> RequiredFeatures
=
532 R
->getValueAsListOfStrings("RequiredFeatures");
533 StringRef IRName
= R
->getValueAsString("IRName");
534 StringRef MaskedIRName
= R
->getValueAsString("MaskedIRName");
535 unsigned NF
= R
->getValueAsInt("NF");
536 bool IsTuple
= R
->getValueAsBit("IsTuple");
537 bool HasFRMRoundModeOp
= R
->getValueAsBit("HasFRMRoundModeOp");
539 const Policy DefaultPolicy
;
540 SmallVector
<Policy
> SupportedUnMaskedPolicies
=
541 RVVIntrinsic::getSupportedUnMaskedPolicies();
542 SmallVector
<Policy
> SupportedMaskedPolicies
=
543 RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy
, HasMaskPolicy
);
545 // Parse prototype and create a list of primitive type with transformers
546 // (operand) in Prototype. Prototype[0] is output operand.
547 SmallVector
<PrototypeDescriptor
> BasicPrototype
=
548 parsePrototypes(Prototypes
);
550 SmallVector
<PrototypeDescriptor
> SuffixDesc
= parsePrototypes(SuffixProto
);
551 SmallVector
<PrototypeDescriptor
> OverloadedSuffixDesc
=
552 parsePrototypes(OverloadedSuffixProto
);
554 // Compute Builtin types
555 auto Prototype
= RVVIntrinsic::computeBuiltinTypes(
556 BasicPrototype
, /*IsMasked=*/false,
557 /*HasMaskedOffOperand=*/false, HasVL
, NF
, UnMaskedPolicyScheme
,
558 DefaultPolicy
, IsTuple
);
559 llvm::SmallVector
<PrototypeDescriptor
> MaskedPrototype
;
561 MaskedPrototype
= RVVIntrinsic::computeBuiltinTypes(
562 BasicPrototype
, /*IsMasked=*/true, HasMaskedOffOperand
, HasVL
, NF
,
563 MaskedPolicyScheme
, DefaultPolicy
, IsTuple
);
565 // Create Intrinsics for each type and LMUL.
566 for (char I
: TypeRange
) {
567 for (int Log2LMUL
: Log2LMULList
) {
568 BasicType BT
= ParseBasicType(I
);
569 std::optional
<RVVTypes
> Types
=
570 TypeCache
.computeTypes(BT
, Log2LMUL
, NF
, Prototype
);
571 // Ignored to create new intrinsic if there are any illegal types.
576 RVVIntrinsic::getSuffixStr(TypeCache
, BT
, Log2LMUL
, SuffixDesc
);
577 auto OverloadedSuffixStr
= RVVIntrinsic::getSuffixStr(
578 TypeCache
, BT
, Log2LMUL
, OverloadedSuffixDesc
);
579 // Create a unmasked intrinsic
580 Out
.push_back(std::make_unique
<RVVIntrinsic
>(
581 Name
, SuffixStr
, OverloadedName
, OverloadedSuffixStr
, IRName
,
582 /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL
,
583 UnMaskedPolicyScheme
, SupportOverloading
, HasBuiltinAlias
,
584 ManualCodegen
, *Types
, IntrinsicTypes
, RequiredFeatures
, NF
,
585 DefaultPolicy
, HasFRMRoundModeOp
));
586 if (UnMaskedPolicyScheme
!= PolicyScheme::SchemeNone
)
587 for (auto P
: SupportedUnMaskedPolicies
) {
588 SmallVector
<PrototypeDescriptor
> PolicyPrototype
=
589 RVVIntrinsic::computeBuiltinTypes(
590 BasicPrototype
, /*IsMasked=*/false,
591 /*HasMaskedOffOperand=*/false, HasVL
, NF
,
592 UnMaskedPolicyScheme
, P
, IsTuple
);
593 std::optional
<RVVTypes
> PolicyTypes
=
594 TypeCache
.computeTypes(BT
, Log2LMUL
, NF
, PolicyPrototype
);
595 Out
.push_back(std::make_unique
<RVVIntrinsic
>(
596 Name
, SuffixStr
, OverloadedName
, OverloadedSuffixStr
, IRName
,
597 /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL
,
598 UnMaskedPolicyScheme
, SupportOverloading
, HasBuiltinAlias
,
599 ManualCodegen
, *PolicyTypes
, IntrinsicTypes
, RequiredFeatures
,
600 NF
, P
, HasFRMRoundModeOp
));
604 // Create a masked intrinsic
605 std::optional
<RVVTypes
> MaskTypes
=
606 TypeCache
.computeTypes(BT
, Log2LMUL
, NF
, MaskedPrototype
);
607 Out
.push_back(std::make_unique
<RVVIntrinsic
>(
608 Name
, SuffixStr
, OverloadedName
, OverloadedSuffixStr
, MaskedIRName
,
609 /*IsMasked=*/true, HasMaskedOffOperand
, HasVL
, MaskedPolicyScheme
,
610 SupportOverloading
, HasBuiltinAlias
, ManualCodegen
, *MaskTypes
,
611 IntrinsicTypes
, RequiredFeatures
, NF
, DefaultPolicy
,
613 if (MaskedPolicyScheme
== PolicyScheme::SchemeNone
)
615 for (auto P
: SupportedMaskedPolicies
) {
616 SmallVector
<PrototypeDescriptor
> PolicyPrototype
=
617 RVVIntrinsic::computeBuiltinTypes(
618 BasicPrototype
, /*IsMasked=*/true, HasMaskedOffOperand
, HasVL
,
619 NF
, MaskedPolicyScheme
, P
, IsTuple
);
620 std::optional
<RVVTypes
> PolicyTypes
=
621 TypeCache
.computeTypes(BT
, Log2LMUL
, NF
, PolicyPrototype
);
622 Out
.push_back(std::make_unique
<RVVIntrinsic
>(
623 Name
, SuffixStr
, OverloadedName
, OverloadedSuffixStr
,
624 MaskedIRName
, /*IsMasked=*/true, HasMaskedOffOperand
, HasVL
,
625 MaskedPolicyScheme
, SupportOverloading
, HasBuiltinAlias
,
626 ManualCodegen
, *PolicyTypes
, IntrinsicTypes
, RequiredFeatures
, NF
,
627 P
, HasFRMRoundModeOp
));
629 } // End for Log2LMULList
630 } // End for TypeRange
632 // We don't emit vsetvli and vsetvlimax for SemaRecord.
633 // They are written in riscv_vector.td and will emit those marco define in
635 if (Name
== "vsetvli" || Name
== "vsetvlimax")
643 SR
.Name
= Name
.str();
644 SR
.OverloadedName
= OverloadedName
.str();
645 BasicType TypeRangeMask
= BasicType::Unknown
;
646 for (char I
: TypeRange
)
647 TypeRangeMask
|= ParseBasicType(I
);
649 SR
.TypeRangeMask
= static_cast<unsigned>(TypeRangeMask
);
651 unsigned Log2LMULMask
= 0;
652 for (int Log2LMUL
: Log2LMULList
)
653 Log2LMULMask
|= 1 << (Log2LMUL
+ 3);
655 SR
.Log2LMULMask
= Log2LMULMask
;
657 SR
.RequiredExtensions
= 0;
658 for (auto RequiredFeature
: RequiredFeatures
) {
659 RVVRequire RequireExt
= StringSwitch
<RVVRequire
>(RequiredFeature
)
660 .Case("RV64", RVV_REQ_RV64
)
661 .Case("ZvfhminOrZvfh", RVV_REQ_ZvfhminOrZvfh
)
662 .Case("Xsfvcp", RVV_REQ_Xsfvcp
)
663 .Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf
)
664 .Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq
)
665 .Case("Xsfvqmaccdod", RVV_REQ_Xsfvqmaccdod
)
666 .Case("Xsfvqmaccqoq", RVV_REQ_Xsfvqmaccqoq
)
667 .Case("Zvbb", RVV_REQ_Zvbb
)
668 .Case("Zvbc", RVV_REQ_Zvbc
)
669 .Case("Zvkb", RVV_REQ_Zvkb
)
670 .Case("Zvkg", RVV_REQ_Zvkg
)
671 .Case("Zvkned", RVV_REQ_Zvkned
)
672 .Case("Zvknha", RVV_REQ_Zvknha
)
673 .Case("Zvknhb", RVV_REQ_Zvknhb
)
674 .Case("Zvksed", RVV_REQ_Zvksed
)
675 .Case("Zvksh", RVV_REQ_Zvksh
)
676 .Default(RVV_REQ_None
);
677 assert(RequireExt
!= RVV_REQ_None
&& "Unrecognized required feature?");
678 SR
.RequiredExtensions
|= RequireExt
;
682 SR
.HasMasked
= HasMasked
;
684 SR
.HasMaskedOffOperand
= HasMaskedOffOperand
;
685 SR
.HasTailPolicy
= HasTailPolicy
;
686 SR
.HasMaskPolicy
= HasMaskPolicy
;
687 SR
.UnMaskedPolicyScheme
= static_cast<uint8_t>(UnMaskedPolicyScheme
);
688 SR
.MaskedPolicyScheme
= static_cast<uint8_t>(MaskedPolicyScheme
);
689 SR
.Prototype
= std::move(BasicPrototype
);
690 SR
.Suffix
= parsePrototypes(SuffixProto
);
691 SR
.OverloadedSuffix
= parsePrototypes(OverloadedSuffixProto
);
692 SR
.IsTuple
= IsTuple
;
693 SR
.HasFRMRoundModeOp
= HasFRMRoundModeOp
;
695 SemaRecords
->push_back(SR
);
699 void RVVEmitter::printHeaderCode(raw_ostream
&OS
) {
700 std::vector
<Record
*> RVVHeaders
=
701 Records
.getAllDerivedDefinitions("RVVHeader");
702 for (auto *R
: RVVHeaders
) {
703 StringRef HeaderCodeStr
= R
->getValueAsString("HeaderCode");
704 OS
<< HeaderCodeStr
.str();
708 void RVVEmitter::createRVVIntrinsicRecords(std::vector
<RVVIntrinsicRecord
> &Out
,
709 SemaSignatureTable
&SST
,
710 ArrayRef
<SemaRecord
> SemaRecords
) {
711 SST
.init(SemaRecords
);
713 for (const auto &SR
: SemaRecords
) {
714 Out
.emplace_back(RVVIntrinsicRecord());
715 RVVIntrinsicRecord
&R
= Out
.back();
716 R
.Name
= SR
.Name
.c_str();
717 R
.OverloadedName
= SR
.OverloadedName
.c_str();
718 R
.PrototypeIndex
= SST
.getIndex(SR
.Prototype
);
719 R
.SuffixIndex
= SST
.getIndex(SR
.Suffix
);
720 R
.OverloadedSuffixIndex
= SST
.getIndex(SR
.OverloadedSuffix
);
721 R
.PrototypeLength
= SR
.Prototype
.size();
722 R
.SuffixLength
= SR
.Suffix
.size();
723 R
.OverloadedSuffixSize
= SR
.OverloadedSuffix
.size();
724 R
.RequiredExtensions
= SR
.RequiredExtensions
;
725 R
.TypeRangeMask
= SR
.TypeRangeMask
;
726 R
.Log2LMULMask
= SR
.Log2LMULMask
;
728 R
.HasMasked
= SR
.HasMasked
;
730 R
.HasMaskedOffOperand
= SR
.HasMaskedOffOperand
;
731 R
.HasTailPolicy
= SR
.HasTailPolicy
;
732 R
.HasMaskPolicy
= SR
.HasMaskPolicy
;
733 R
.UnMaskedPolicyScheme
= SR
.UnMaskedPolicyScheme
;
734 R
.MaskedPolicyScheme
= SR
.MaskedPolicyScheme
;
735 R
.IsTuple
= SR
.IsTuple
;
736 R
.HasFRMRoundModeOp
= SR
.HasFRMRoundModeOp
;
738 assert(R
.PrototypeIndex
!=
739 static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX
));
740 assert(R
.SuffixIndex
!=
741 static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX
));
742 assert(R
.OverloadedSuffixIndex
!=
743 static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX
));
747 void RVVEmitter::createSema(raw_ostream
&OS
) {
748 std::vector
<std::unique_ptr
<RVVIntrinsic
>> Defs
;
749 std::vector
<RVVIntrinsicRecord
> RVVIntrinsicRecords
;
750 SemaSignatureTable SST
;
751 std::vector
<SemaRecord
> SemaRecords
;
753 createRVVIntrinsics(Defs
, &SemaRecords
);
755 createRVVIntrinsicRecords(RVVIntrinsicRecords
, SST
, SemaRecords
);
757 // Emit signature table for SemaRISCVVectorLookup.cpp.
758 OS
<< "#ifdef DECL_SIGNATURE_TABLE\n";
762 // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp.
763 OS
<< "#ifdef DECL_INTRINSIC_RECORDS\n";
764 for (const RVVIntrinsicRecord
&Record
: RVVIntrinsicRecords
)
770 void EmitRVVHeader(RecordKeeper
&Records
, raw_ostream
&OS
) {
771 RVVEmitter(Records
).createHeader(OS
);
774 void EmitRVVBuiltins(RecordKeeper
&Records
, raw_ostream
&OS
) {
775 RVVEmitter(Records
).createBuiltins(OS
);
778 void EmitRVVBuiltinCG(RecordKeeper
&Records
, raw_ostream
&OS
) {
779 RVVEmitter(Records
).createCodeGen(OS
);
782 void EmitRVVBuiltinSema(RecordKeeper
&Records
, raw_ostream
&OS
) {
783 RVVEmitter(Records
).createSema(OS
);
786 } // End namespace clang