Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp
35233 views
1
//===- RISCVVIntrinsicUtils.cpp - 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
#include "clang/Support/RISCVVIntrinsicUtils.h"
10
#include "llvm/ADT/ArrayRef.h"
11
#include "llvm/ADT/SmallSet.h"
12
#include "llvm/ADT/StringExtras.h"
13
#include "llvm/ADT/StringSet.h"
14
#include "llvm/ADT/Twine.h"
15
#include "llvm/Support/ErrorHandling.h"
16
#include "llvm/Support/raw_ostream.h"
17
#include <numeric>
18
#include <optional>
19
20
using namespace llvm;
21
22
namespace clang {
23
namespace RISCV {
24
25
const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
26
BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
27
const PrototypeDescriptor PrototypeDescriptor::VL =
28
PrototypeDescriptor(BaseTypeModifier::SizeT);
29
const PrototypeDescriptor PrototypeDescriptor::Vector =
30
PrototypeDescriptor(BaseTypeModifier::Vector);
31
32
//===----------------------------------------------------------------------===//
33
// Type implementation
34
//===----------------------------------------------------------------------===//
35
36
LMULType::LMULType(int NewLog2LMUL) {
37
// Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
38
assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
39
Log2LMUL = NewLog2LMUL;
40
}
41
42
std::string LMULType::str() const {
43
if (Log2LMUL < 0)
44
return "mf" + utostr(1ULL << (-Log2LMUL));
45
return "m" + utostr(1ULL << Log2LMUL);
46
}
47
48
VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
49
int Log2ScaleResult = 0;
50
switch (ElementBitwidth) {
51
default:
52
break;
53
case 8:
54
Log2ScaleResult = Log2LMUL + 3;
55
break;
56
case 16:
57
Log2ScaleResult = Log2LMUL + 2;
58
break;
59
case 32:
60
Log2ScaleResult = Log2LMUL + 1;
61
break;
62
case 64:
63
Log2ScaleResult = Log2LMUL;
64
break;
65
}
66
// Illegal vscale result would be less than 1
67
if (Log2ScaleResult < 0)
68
return std::nullopt;
69
return 1 << Log2ScaleResult;
70
}
71
72
void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
73
74
RVVType::RVVType(BasicType BT, int Log2LMUL,
75
const PrototypeDescriptor &prototype)
76
: BT(BT), LMUL(LMULType(Log2LMUL)) {
77
applyBasicType();
78
applyModifier(prototype);
79
Valid = verifyType();
80
if (Valid) {
81
initBuiltinStr();
82
initTypeStr();
83
if (isVector()) {
84
initClangBuiltinStr();
85
}
86
}
87
}
88
89
// clang-format off
90
// boolean type are encoded the ratio of n (SEW/LMUL)
91
// SEW/LMUL | 1 | 2 | 4 | 8 | 16 | 32 | 64
92
// c type | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t | vbool2_t | vbool1_t
93
// IR type | nxv1i1 | nxv2i1 | nxv4i1 | nxv8i1 | nxv16i1 | nxv32i1 | nxv64i1
94
95
// type\lmul | 1/8 | 1/4 | 1/2 | 1 | 2 | 4 | 8
96
// -------- |------ | -------- | ------- | ------- | -------- | -------- | --------
97
// i64 | N/A | N/A | N/A | nxv1i64 | nxv2i64 | nxv4i64 | nxv8i64
98
// i32 | N/A | N/A | nxv1i32 | nxv2i32 | nxv4i32 | nxv8i32 | nxv16i32
99
// i16 | N/A | nxv1i16 | nxv2i16 | nxv4i16 | nxv8i16 | nxv16i16 | nxv32i16
100
// i8 | nxv1i8 | nxv2i8 | nxv4i8 | nxv8i8 | nxv16i8 | nxv32i8 | nxv64i8
101
// double | N/A | N/A | N/A | nxv1f64 | nxv2f64 | nxv4f64 | nxv8f64
102
// float | N/A | N/A | nxv1f32 | nxv2f32 | nxv4f32 | nxv8f32 | nxv16f32
103
// half | N/A | nxv1f16 | nxv2f16 | nxv4f16 | nxv8f16 | nxv16f16 | nxv32f16
104
// bfloat16 | N/A | nxv1bf16 | nxv2bf16| nxv4bf16| nxv8bf16 | nxv16bf16| nxv32bf16
105
// clang-format on
106
107
bool RVVType::verifyType() const {
108
if (ScalarType == Invalid)
109
return false;
110
if (isScalar())
111
return true;
112
if (!Scale)
113
return false;
114
if (isFloat() && ElementBitwidth == 8)
115
return false;
116
if (isBFloat() && ElementBitwidth != 16)
117
return false;
118
if (IsTuple && (NF == 1 || NF > 8))
119
return false;
120
if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
121
return false;
122
unsigned V = *Scale;
123
switch (ElementBitwidth) {
124
case 1:
125
case 8:
126
// Check Scale is 1,2,4,8,16,32,64
127
return (V <= 64 && isPowerOf2_32(V));
128
case 16:
129
// Check Scale is 1,2,4,8,16,32
130
return (V <= 32 && isPowerOf2_32(V));
131
case 32:
132
// Check Scale is 1,2,4,8,16
133
return (V <= 16 && isPowerOf2_32(V));
134
case 64:
135
// Check Scale is 1,2,4,8
136
return (V <= 8 && isPowerOf2_32(V));
137
}
138
return false;
139
}
140
141
void RVVType::initBuiltinStr() {
142
assert(isValid() && "RVVType is invalid");
143
switch (ScalarType) {
144
case ScalarTypeKind::Void:
145
BuiltinStr = "v";
146
return;
147
case ScalarTypeKind::Size_t:
148
BuiltinStr = "z";
149
if (IsImmediate)
150
BuiltinStr = "I" + BuiltinStr;
151
if (IsPointer)
152
BuiltinStr += "*";
153
return;
154
case ScalarTypeKind::Ptrdiff_t:
155
BuiltinStr = "Y";
156
return;
157
case ScalarTypeKind::UnsignedLong:
158
BuiltinStr = "ULi";
159
return;
160
case ScalarTypeKind::SignedLong:
161
BuiltinStr = "Li";
162
return;
163
case ScalarTypeKind::Boolean:
164
assert(ElementBitwidth == 1);
165
BuiltinStr += "b";
166
break;
167
case ScalarTypeKind::SignedInteger:
168
case ScalarTypeKind::UnsignedInteger:
169
switch (ElementBitwidth) {
170
case 8:
171
BuiltinStr += "c";
172
break;
173
case 16:
174
BuiltinStr += "s";
175
break;
176
case 32:
177
BuiltinStr += "i";
178
break;
179
case 64:
180
BuiltinStr += "Wi";
181
break;
182
default:
183
llvm_unreachable("Unhandled ElementBitwidth!");
184
}
185
if (isSignedInteger())
186
BuiltinStr = "S" + BuiltinStr;
187
else
188
BuiltinStr = "U" + BuiltinStr;
189
break;
190
case ScalarTypeKind::Float:
191
switch (ElementBitwidth) {
192
case 16:
193
BuiltinStr += "x";
194
break;
195
case 32:
196
BuiltinStr += "f";
197
break;
198
case 64:
199
BuiltinStr += "d";
200
break;
201
default:
202
llvm_unreachable("Unhandled ElementBitwidth!");
203
}
204
break;
205
case ScalarTypeKind::BFloat:
206
BuiltinStr += "y";
207
break;
208
default:
209
llvm_unreachable("ScalarType is invalid!");
210
}
211
if (IsImmediate)
212
BuiltinStr = "I" + BuiltinStr;
213
if (isScalar()) {
214
if (IsConstant)
215
BuiltinStr += "C";
216
if (IsPointer)
217
BuiltinStr += "*";
218
return;
219
}
220
BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
221
// Pointer to vector types. Defined for segment load intrinsics.
222
// segment load intrinsics have pointer type arguments to store the loaded
223
// vector values.
224
if (IsPointer)
225
BuiltinStr += "*";
226
227
if (IsTuple)
228
BuiltinStr = "T" + utostr(NF) + BuiltinStr;
229
}
230
231
void RVVType::initClangBuiltinStr() {
232
assert(isValid() && "RVVType is invalid");
233
assert(isVector() && "Handle Vector type only");
234
235
ClangBuiltinStr = "__rvv_";
236
switch (ScalarType) {
237
case ScalarTypeKind::Boolean:
238
ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
239
return;
240
case ScalarTypeKind::Float:
241
ClangBuiltinStr += "float";
242
break;
243
case ScalarTypeKind::BFloat:
244
ClangBuiltinStr += "bfloat";
245
break;
246
case ScalarTypeKind::SignedInteger:
247
ClangBuiltinStr += "int";
248
break;
249
case ScalarTypeKind::UnsignedInteger:
250
ClangBuiltinStr += "uint";
251
break;
252
default:
253
llvm_unreachable("ScalarTypeKind is invalid");
254
}
255
ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
256
(IsTuple ? "x" + utostr(NF) : "") + "_t";
257
}
258
259
void RVVType::initTypeStr() {
260
assert(isValid() && "RVVType is invalid");
261
262
if (IsConstant)
263
Str += "const ";
264
265
auto getTypeString = [&](StringRef TypeStr) {
266
if (isScalar())
267
return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
268
return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
269
(IsTuple ? "x" + utostr(NF) : "") + "_t")
270
.str();
271
};
272
273
switch (ScalarType) {
274
case ScalarTypeKind::Void:
275
Str = "void";
276
return;
277
case ScalarTypeKind::Size_t:
278
Str = "size_t";
279
if (IsPointer)
280
Str += " *";
281
return;
282
case ScalarTypeKind::Ptrdiff_t:
283
Str = "ptrdiff_t";
284
return;
285
case ScalarTypeKind::UnsignedLong:
286
Str = "unsigned long";
287
return;
288
case ScalarTypeKind::SignedLong:
289
Str = "long";
290
return;
291
case ScalarTypeKind::Boolean:
292
if (isScalar())
293
Str += "bool";
294
else
295
// Vector bool is special case, the formulate is
296
// `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
297
Str += "vbool" + utostr(64 / *Scale) + "_t";
298
break;
299
case ScalarTypeKind::Float:
300
if (isScalar()) {
301
if (ElementBitwidth == 64)
302
Str += "double";
303
else if (ElementBitwidth == 32)
304
Str += "float";
305
else if (ElementBitwidth == 16)
306
Str += "_Float16";
307
else
308
llvm_unreachable("Unhandled floating type.");
309
} else
310
Str += getTypeString("float");
311
break;
312
case ScalarTypeKind::BFloat:
313
if (isScalar()) {
314
if (ElementBitwidth == 16)
315
Str += "__bf16";
316
else
317
llvm_unreachable("Unhandled floating type.");
318
} else
319
Str += getTypeString("bfloat");
320
break;
321
case ScalarTypeKind::SignedInteger:
322
Str += getTypeString("int");
323
break;
324
case ScalarTypeKind::UnsignedInteger:
325
Str += getTypeString("uint");
326
break;
327
default:
328
llvm_unreachable("ScalarType is invalid!");
329
}
330
if (IsPointer)
331
Str += " *";
332
}
333
334
void RVVType::initShortStr() {
335
switch (ScalarType) {
336
case ScalarTypeKind::Boolean:
337
assert(isVector());
338
ShortStr = "b" + utostr(64 / *Scale);
339
return;
340
case ScalarTypeKind::Float:
341
ShortStr = "f" + utostr(ElementBitwidth);
342
break;
343
case ScalarTypeKind::BFloat:
344
ShortStr = "bf" + utostr(ElementBitwidth);
345
break;
346
case ScalarTypeKind::SignedInteger:
347
ShortStr = "i" + utostr(ElementBitwidth);
348
break;
349
case ScalarTypeKind::UnsignedInteger:
350
ShortStr = "u" + utostr(ElementBitwidth);
351
break;
352
default:
353
llvm_unreachable("Unhandled case!");
354
}
355
if (isVector())
356
ShortStr += LMUL.str();
357
if (isTuple())
358
ShortStr += "x" + utostr(NF);
359
}
360
361
static VectorTypeModifier getTupleVTM(unsigned NF) {
362
assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
363
return static_cast<VectorTypeModifier>(
364
static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
365
}
366
367
void RVVType::applyBasicType() {
368
switch (BT) {
369
case BasicType::Int8:
370
ElementBitwidth = 8;
371
ScalarType = ScalarTypeKind::SignedInteger;
372
break;
373
case BasicType::Int16:
374
ElementBitwidth = 16;
375
ScalarType = ScalarTypeKind::SignedInteger;
376
break;
377
case BasicType::Int32:
378
ElementBitwidth = 32;
379
ScalarType = ScalarTypeKind::SignedInteger;
380
break;
381
case BasicType::Int64:
382
ElementBitwidth = 64;
383
ScalarType = ScalarTypeKind::SignedInteger;
384
break;
385
case BasicType::Float16:
386
ElementBitwidth = 16;
387
ScalarType = ScalarTypeKind::Float;
388
break;
389
case BasicType::Float32:
390
ElementBitwidth = 32;
391
ScalarType = ScalarTypeKind::Float;
392
break;
393
case BasicType::Float64:
394
ElementBitwidth = 64;
395
ScalarType = ScalarTypeKind::Float;
396
break;
397
case BasicType::BFloat16:
398
ElementBitwidth = 16;
399
ScalarType = ScalarTypeKind::BFloat;
400
break;
401
default:
402
llvm_unreachable("Unhandled type code!");
403
}
404
assert(ElementBitwidth != 0 && "Bad element bitwidth!");
405
}
406
407
std::optional<PrototypeDescriptor>
408
PrototypeDescriptor::parsePrototypeDescriptor(
409
llvm::StringRef PrototypeDescriptorStr) {
410
PrototypeDescriptor PD;
411
BaseTypeModifier PT = BaseTypeModifier::Invalid;
412
VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
413
414
if (PrototypeDescriptorStr.empty())
415
return PD;
416
417
// Handle base type modifier
418
auto PType = PrototypeDescriptorStr.back();
419
switch (PType) {
420
case 'e':
421
PT = BaseTypeModifier::Scalar;
422
break;
423
case 'v':
424
PT = BaseTypeModifier::Vector;
425
break;
426
case 'w':
427
PT = BaseTypeModifier::Vector;
428
VTM = VectorTypeModifier::Widening2XVector;
429
break;
430
case 'q':
431
PT = BaseTypeModifier::Vector;
432
VTM = VectorTypeModifier::Widening4XVector;
433
break;
434
case 'o':
435
PT = BaseTypeModifier::Vector;
436
VTM = VectorTypeModifier::Widening8XVector;
437
break;
438
case 'm':
439
PT = BaseTypeModifier::Vector;
440
VTM = VectorTypeModifier::MaskVector;
441
break;
442
case '0':
443
PT = BaseTypeModifier::Void;
444
break;
445
case 'z':
446
PT = BaseTypeModifier::SizeT;
447
break;
448
case 't':
449
PT = BaseTypeModifier::Ptrdiff;
450
break;
451
case 'u':
452
PT = BaseTypeModifier::UnsignedLong;
453
break;
454
case 'l':
455
PT = BaseTypeModifier::SignedLong;
456
break;
457
case 'f':
458
PT = BaseTypeModifier::Float32;
459
break;
460
default:
461
llvm_unreachable("Illegal primitive type transformers!");
462
}
463
PD.PT = static_cast<uint8_t>(PT);
464
PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
465
466
// Compute the vector type transformers, it can only appear one time.
467
if (PrototypeDescriptorStr.starts_with("(")) {
468
assert(VTM == VectorTypeModifier::NoModifier &&
469
"VectorTypeModifier should only have one modifier");
470
size_t Idx = PrototypeDescriptorStr.find(')');
471
assert(Idx != StringRef::npos);
472
StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
473
PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
474
assert(!PrototypeDescriptorStr.contains('(') &&
475
"Only allow one vector type modifier");
476
477
auto ComplexTT = ComplexType.split(":");
478
if (ComplexTT.first == "Log2EEW") {
479
uint32_t Log2EEW;
480
if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
481
llvm_unreachable("Invalid Log2EEW value!");
482
return std::nullopt;
483
}
484
switch (Log2EEW) {
485
case 3:
486
VTM = VectorTypeModifier::Log2EEW3;
487
break;
488
case 4:
489
VTM = VectorTypeModifier::Log2EEW4;
490
break;
491
case 5:
492
VTM = VectorTypeModifier::Log2EEW5;
493
break;
494
case 6:
495
VTM = VectorTypeModifier::Log2EEW6;
496
break;
497
default:
498
llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
499
return std::nullopt;
500
}
501
} else if (ComplexTT.first == "FixedSEW") {
502
uint32_t NewSEW;
503
if (ComplexTT.second.getAsInteger(10, NewSEW)) {
504
llvm_unreachable("Invalid FixedSEW value!");
505
return std::nullopt;
506
}
507
switch (NewSEW) {
508
case 8:
509
VTM = VectorTypeModifier::FixedSEW8;
510
break;
511
case 16:
512
VTM = VectorTypeModifier::FixedSEW16;
513
break;
514
case 32:
515
VTM = VectorTypeModifier::FixedSEW32;
516
break;
517
case 64:
518
VTM = VectorTypeModifier::FixedSEW64;
519
break;
520
default:
521
llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
522
return std::nullopt;
523
}
524
} else if (ComplexTT.first == "LFixedLog2LMUL") {
525
int32_t Log2LMUL;
526
if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
527
llvm_unreachable("Invalid LFixedLog2LMUL value!");
528
return std::nullopt;
529
}
530
switch (Log2LMUL) {
531
case -3:
532
VTM = VectorTypeModifier::LFixedLog2LMULN3;
533
break;
534
case -2:
535
VTM = VectorTypeModifier::LFixedLog2LMULN2;
536
break;
537
case -1:
538
VTM = VectorTypeModifier::LFixedLog2LMULN1;
539
break;
540
case 0:
541
VTM = VectorTypeModifier::LFixedLog2LMUL0;
542
break;
543
case 1:
544
VTM = VectorTypeModifier::LFixedLog2LMUL1;
545
break;
546
case 2:
547
VTM = VectorTypeModifier::LFixedLog2LMUL2;
548
break;
549
case 3:
550
VTM = VectorTypeModifier::LFixedLog2LMUL3;
551
break;
552
default:
553
llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
554
return std::nullopt;
555
}
556
} else if (ComplexTT.first == "SFixedLog2LMUL") {
557
int32_t Log2LMUL;
558
if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
559
llvm_unreachable("Invalid SFixedLog2LMUL value!");
560
return std::nullopt;
561
}
562
switch (Log2LMUL) {
563
case -3:
564
VTM = VectorTypeModifier::SFixedLog2LMULN3;
565
break;
566
case -2:
567
VTM = VectorTypeModifier::SFixedLog2LMULN2;
568
break;
569
case -1:
570
VTM = VectorTypeModifier::SFixedLog2LMULN1;
571
break;
572
case 0:
573
VTM = VectorTypeModifier::SFixedLog2LMUL0;
574
break;
575
case 1:
576
VTM = VectorTypeModifier::SFixedLog2LMUL1;
577
break;
578
case 2:
579
VTM = VectorTypeModifier::SFixedLog2LMUL2;
580
break;
581
case 3:
582
VTM = VectorTypeModifier::SFixedLog2LMUL3;
583
break;
584
default:
585
llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
586
return std::nullopt;
587
}
588
589
} else if (ComplexTT.first == "SEFixedLog2LMUL") {
590
int32_t Log2LMUL;
591
if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
592
llvm_unreachable("Invalid SEFixedLog2LMUL value!");
593
return std::nullopt;
594
}
595
switch (Log2LMUL) {
596
case -3:
597
VTM = VectorTypeModifier::SEFixedLog2LMULN3;
598
break;
599
case -2:
600
VTM = VectorTypeModifier::SEFixedLog2LMULN2;
601
break;
602
case -1:
603
VTM = VectorTypeModifier::SEFixedLog2LMULN1;
604
break;
605
case 0:
606
VTM = VectorTypeModifier::SEFixedLog2LMUL0;
607
break;
608
case 1:
609
VTM = VectorTypeModifier::SEFixedLog2LMUL1;
610
break;
611
case 2:
612
VTM = VectorTypeModifier::SEFixedLog2LMUL2;
613
break;
614
case 3:
615
VTM = VectorTypeModifier::SEFixedLog2LMUL3;
616
break;
617
default:
618
llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
619
return std::nullopt;
620
}
621
} else if (ComplexTT.first == "Tuple") {
622
unsigned NF = 0;
623
if (ComplexTT.second.getAsInteger(10, NF)) {
624
llvm_unreachable("Invalid NF value!");
625
return std::nullopt;
626
}
627
VTM = getTupleVTM(NF);
628
} else {
629
llvm_unreachable("Illegal complex type transformers!");
630
}
631
}
632
PD.VTM = static_cast<uint8_t>(VTM);
633
634
// Compute the remain type transformers
635
TypeModifier TM = TypeModifier::NoModifier;
636
for (char I : PrototypeDescriptorStr) {
637
switch (I) {
638
case 'P':
639
if ((TM & TypeModifier::Const) == TypeModifier::Const)
640
llvm_unreachable("'P' transformer cannot be used after 'C'");
641
if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
642
llvm_unreachable("'P' transformer cannot be used twice");
643
TM |= TypeModifier::Pointer;
644
break;
645
case 'C':
646
TM |= TypeModifier::Const;
647
break;
648
case 'K':
649
TM |= TypeModifier::Immediate;
650
break;
651
case 'U':
652
TM |= TypeModifier::UnsignedInteger;
653
break;
654
case 'I':
655
TM |= TypeModifier::SignedInteger;
656
break;
657
case 'F':
658
TM |= TypeModifier::Float;
659
break;
660
case 'S':
661
TM |= TypeModifier::LMUL1;
662
break;
663
default:
664
llvm_unreachable("Illegal non-primitive type transformer!");
665
}
666
}
667
PD.TM = static_cast<uint8_t>(TM);
668
669
return PD;
670
}
671
672
void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
673
// Handle primitive type transformer
674
switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
675
case BaseTypeModifier::Scalar:
676
Scale = 0;
677
break;
678
case BaseTypeModifier::Vector:
679
Scale = LMUL.getScale(ElementBitwidth);
680
break;
681
case BaseTypeModifier::Void:
682
ScalarType = ScalarTypeKind::Void;
683
break;
684
case BaseTypeModifier::SizeT:
685
ScalarType = ScalarTypeKind::Size_t;
686
break;
687
case BaseTypeModifier::Ptrdiff:
688
ScalarType = ScalarTypeKind::Ptrdiff_t;
689
break;
690
case BaseTypeModifier::UnsignedLong:
691
ScalarType = ScalarTypeKind::UnsignedLong;
692
break;
693
case BaseTypeModifier::SignedLong:
694
ScalarType = ScalarTypeKind::SignedLong;
695
break;
696
case BaseTypeModifier::Float32:
697
ElementBitwidth = 32;
698
ScalarType = ScalarTypeKind::Float;
699
break;
700
case BaseTypeModifier::Invalid:
701
ScalarType = ScalarTypeKind::Invalid;
702
return;
703
}
704
705
switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
706
case VectorTypeModifier::Widening2XVector:
707
ElementBitwidth *= 2;
708
LMUL.MulLog2LMUL(1);
709
Scale = LMUL.getScale(ElementBitwidth);
710
break;
711
case VectorTypeModifier::Widening4XVector:
712
ElementBitwidth *= 4;
713
LMUL.MulLog2LMUL(2);
714
Scale = LMUL.getScale(ElementBitwidth);
715
break;
716
case VectorTypeModifier::Widening8XVector:
717
ElementBitwidth *= 8;
718
LMUL.MulLog2LMUL(3);
719
Scale = LMUL.getScale(ElementBitwidth);
720
break;
721
case VectorTypeModifier::MaskVector:
722
ScalarType = ScalarTypeKind::Boolean;
723
Scale = LMUL.getScale(ElementBitwidth);
724
ElementBitwidth = 1;
725
break;
726
case VectorTypeModifier::Log2EEW3:
727
applyLog2EEW(3);
728
break;
729
case VectorTypeModifier::Log2EEW4:
730
applyLog2EEW(4);
731
break;
732
case VectorTypeModifier::Log2EEW5:
733
applyLog2EEW(5);
734
break;
735
case VectorTypeModifier::Log2EEW6:
736
applyLog2EEW(6);
737
break;
738
case VectorTypeModifier::FixedSEW8:
739
applyFixedSEW(8);
740
break;
741
case VectorTypeModifier::FixedSEW16:
742
applyFixedSEW(16);
743
break;
744
case VectorTypeModifier::FixedSEW32:
745
applyFixedSEW(32);
746
break;
747
case VectorTypeModifier::FixedSEW64:
748
applyFixedSEW(64);
749
break;
750
case VectorTypeModifier::LFixedLog2LMULN3:
751
applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
752
break;
753
case VectorTypeModifier::LFixedLog2LMULN2:
754
applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
755
break;
756
case VectorTypeModifier::LFixedLog2LMULN1:
757
applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
758
break;
759
case VectorTypeModifier::LFixedLog2LMUL0:
760
applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
761
break;
762
case VectorTypeModifier::LFixedLog2LMUL1:
763
applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
764
break;
765
case VectorTypeModifier::LFixedLog2LMUL2:
766
applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
767
break;
768
case VectorTypeModifier::LFixedLog2LMUL3:
769
applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
770
break;
771
case VectorTypeModifier::SFixedLog2LMULN3:
772
applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
773
break;
774
case VectorTypeModifier::SFixedLog2LMULN2:
775
applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
776
break;
777
case VectorTypeModifier::SFixedLog2LMULN1:
778
applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
779
break;
780
case VectorTypeModifier::SFixedLog2LMUL0:
781
applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
782
break;
783
case VectorTypeModifier::SFixedLog2LMUL1:
784
applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
785
break;
786
case VectorTypeModifier::SFixedLog2LMUL2:
787
applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
788
break;
789
case VectorTypeModifier::SFixedLog2LMUL3:
790
applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
791
break;
792
case VectorTypeModifier::SEFixedLog2LMULN3:
793
applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
794
break;
795
case VectorTypeModifier::SEFixedLog2LMULN2:
796
applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
797
break;
798
case VectorTypeModifier::SEFixedLog2LMULN1:
799
applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
800
break;
801
case VectorTypeModifier::SEFixedLog2LMUL0:
802
applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
803
break;
804
case VectorTypeModifier::SEFixedLog2LMUL1:
805
applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
806
break;
807
case VectorTypeModifier::SEFixedLog2LMUL2:
808
applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
809
break;
810
case VectorTypeModifier::SEFixedLog2LMUL3:
811
applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
812
break;
813
case VectorTypeModifier::Tuple2:
814
case VectorTypeModifier::Tuple3:
815
case VectorTypeModifier::Tuple4:
816
case VectorTypeModifier::Tuple5:
817
case VectorTypeModifier::Tuple6:
818
case VectorTypeModifier::Tuple7:
819
case VectorTypeModifier::Tuple8: {
820
IsTuple = true;
821
NF = 2 + static_cast<uint8_t>(Transformer.VTM) -
822
static_cast<uint8_t>(VectorTypeModifier::Tuple2);
823
break;
824
}
825
case VectorTypeModifier::NoModifier:
826
break;
827
}
828
829
// Early return if the current type modifier is already invalid.
830
if (ScalarType == Invalid)
831
return;
832
833
for (unsigned TypeModifierMaskShift = 0;
834
TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
835
++TypeModifierMaskShift) {
836
unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
837
if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
838
TypeModifierMask)
839
continue;
840
switch (static_cast<TypeModifier>(TypeModifierMask)) {
841
case TypeModifier::Pointer:
842
IsPointer = true;
843
break;
844
case TypeModifier::Const:
845
IsConstant = true;
846
break;
847
case TypeModifier::Immediate:
848
IsImmediate = true;
849
IsConstant = true;
850
break;
851
case TypeModifier::UnsignedInteger:
852
ScalarType = ScalarTypeKind::UnsignedInteger;
853
break;
854
case TypeModifier::SignedInteger:
855
ScalarType = ScalarTypeKind::SignedInteger;
856
break;
857
case TypeModifier::Float:
858
ScalarType = ScalarTypeKind::Float;
859
break;
860
case TypeModifier::BFloat:
861
ScalarType = ScalarTypeKind::BFloat;
862
break;
863
case TypeModifier::LMUL1:
864
LMUL = LMULType(0);
865
// Update ElementBitwidth need to update Scale too.
866
Scale = LMUL.getScale(ElementBitwidth);
867
break;
868
default:
869
llvm_unreachable("Unknown type modifier mask!");
870
}
871
}
872
}
873
874
void RVVType::applyLog2EEW(unsigned Log2EEW) {
875
// update new elmul = (eew/sew) * lmul
876
LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
877
// update new eew
878
ElementBitwidth = 1 << Log2EEW;
879
ScalarType = ScalarTypeKind::SignedInteger;
880
Scale = LMUL.getScale(ElementBitwidth);
881
}
882
883
void RVVType::applyFixedSEW(unsigned NewSEW) {
884
// Set invalid type if src and dst SEW are same.
885
if (ElementBitwidth == NewSEW) {
886
ScalarType = ScalarTypeKind::Invalid;
887
return;
888
}
889
// Update new SEW
890
ElementBitwidth = NewSEW;
891
Scale = LMUL.getScale(ElementBitwidth);
892
}
893
894
void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
895
switch (Type) {
896
case FixedLMULType::LargerThan:
897
if (Log2LMUL <= LMUL.Log2LMUL) {
898
ScalarType = ScalarTypeKind::Invalid;
899
return;
900
}
901
break;
902
case FixedLMULType::SmallerThan:
903
if (Log2LMUL >= LMUL.Log2LMUL) {
904
ScalarType = ScalarTypeKind::Invalid;
905
return;
906
}
907
break;
908
case FixedLMULType::SmallerOrEqual:
909
if (Log2LMUL > LMUL.Log2LMUL) {
910
ScalarType = ScalarTypeKind::Invalid;
911
return;
912
}
913
break;
914
}
915
916
// Update new LMUL
917
LMUL = LMULType(Log2LMUL);
918
Scale = LMUL.getScale(ElementBitwidth);
919
}
920
921
std::optional<RVVTypes>
922
RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
923
ArrayRef<PrototypeDescriptor> Prototype) {
924
RVVTypes Types;
925
for (const PrototypeDescriptor &Proto : Prototype) {
926
auto T = computeType(BT, Log2LMUL, Proto);
927
if (!T)
928
return std::nullopt;
929
// Record legal type index
930
Types.push_back(*T);
931
}
932
return Types;
933
}
934
935
// Compute the hash value of RVVType, used for cache the result of computeType.
936
static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
937
PrototypeDescriptor Proto) {
938
// Layout of hash value:
939
// 0 8 16 24 32 40
940
// | Log2LMUL + 3 | BT | Proto.PT | Proto.TM | Proto.VTM |
941
assert(Log2LMUL >= -3 && Log2LMUL <= 3);
942
return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
943
((uint64_t)(Proto.PT & 0xff) << 16) |
944
((uint64_t)(Proto.TM & 0xff) << 24) |
945
((uint64_t)(Proto.VTM & 0xff) << 32);
946
}
947
948
std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
949
PrototypeDescriptor Proto) {
950
uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
951
// Search first
952
auto It = LegalTypes.find(Idx);
953
if (It != LegalTypes.end())
954
return &(It->second);
955
956
if (IllegalTypes.count(Idx))
957
return std::nullopt;
958
959
// Compute type and record the result.
960
RVVType T(BT, Log2LMUL, Proto);
961
if (T.isValid()) {
962
// Record legal type index and value.
963
std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
964
InsertResult = LegalTypes.insert({Idx, T});
965
return &(InsertResult.first->second);
966
}
967
// Record illegal type index.
968
IllegalTypes.insert(Idx);
969
return std::nullopt;
970
}
971
972
//===----------------------------------------------------------------------===//
973
// RVVIntrinsic implementation
974
//===----------------------------------------------------------------------===//
975
RVVIntrinsic::RVVIntrinsic(
976
StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
977
StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
978
bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
979
bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
980
const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
981
unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
982
: IRName(IRName), IsMasked(IsMasked),
983
HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
984
SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
985
ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
986
987
// Init BuiltinName, Name and OverloadedName
988
BuiltinName = NewName.str();
989
Name = BuiltinName;
990
if (NewOverloadedName.empty())
991
OverloadedName = NewName.split("_").first.str();
992
else
993
OverloadedName = NewOverloadedName.str();
994
if (!Suffix.empty())
995
Name += "_" + Suffix.str();
996
if (!OverloadedSuffix.empty())
997
OverloadedName += "_" + OverloadedSuffix.str();
998
999
updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
1000
PolicyAttrs, HasFRMRoundModeOp);
1001
1002
// Init OutputType and InputTypes
1003
OutputType = OutInTypes[0];
1004
InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1005
1006
// IntrinsicTypes is unmasked TA version index. Need to update it
1007
// if there is merge operand (It is always in first operand).
1008
IntrinsicTypes = NewIntrinsicTypes;
1009
if ((IsMasked && hasMaskedOffOperand()) ||
1010
(!IsMasked && hasPassthruOperand())) {
1011
for (auto &I : IntrinsicTypes) {
1012
if (I >= 0)
1013
I += NF;
1014
}
1015
}
1016
}
1017
1018
std::string RVVIntrinsic::getBuiltinTypeStr() const {
1019
std::string S;
1020
S += OutputType->getBuiltinStr();
1021
for (const auto &T : InputTypes) {
1022
S += T->getBuiltinStr();
1023
}
1024
return S;
1025
}
1026
1027
std::string RVVIntrinsic::getSuffixStr(
1028
RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
1029
llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
1030
SmallVector<std::string> SuffixStrs;
1031
for (auto PD : PrototypeDescriptors) {
1032
auto T = TypeCache.computeType(Type, Log2LMUL, PD);
1033
SuffixStrs.push_back((*T)->getShortStr());
1034
}
1035
return join(SuffixStrs, "_");
1036
}
1037
1038
llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
1039
llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
1040
bool HasMaskedOffOperand, bool HasVL, unsigned NF,
1041
PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
1042
SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
1043
Prototype.end());
1044
bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
1045
if (IsMasked) {
1046
// If HasMaskedOffOperand, insert result type as first input operand if
1047
// need.
1048
if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1049
if (NF == 1) {
1050
NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1051
} else if (NF > 1) {
1052
if (IsTuple) {
1053
PrototypeDescriptor BasePtrOperand = Prototype[1];
1054
PrototypeDescriptor MaskoffType = PrototypeDescriptor(
1055
static_cast<uint8_t>(BaseTypeModifier::Vector),
1056
static_cast<uint8_t>(getTupleVTM(NF)),
1057
BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1058
NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1059
} else {
1060
// Convert
1061
// (void, op0 address, op1 address, ...)
1062
// to
1063
// (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1064
PrototypeDescriptor MaskoffType = NewPrototype[1];
1065
MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1066
NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1067
}
1068
}
1069
}
1070
if (HasMaskedOffOperand && NF > 1) {
1071
// Convert
1072
// (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1073
// to
1074
// (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1075
// ...)
1076
if (IsTuple)
1077
NewPrototype.insert(NewPrototype.begin() + 1,
1078
PrototypeDescriptor::Mask);
1079
else
1080
NewPrototype.insert(NewPrototype.begin() + NF + 1,
1081
PrototypeDescriptor::Mask);
1082
} else {
1083
// If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
1084
NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
1085
}
1086
} else {
1087
if (NF == 1) {
1088
if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1089
NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1090
} else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1091
if (IsTuple) {
1092
PrototypeDescriptor BasePtrOperand = Prototype[0];
1093
PrototypeDescriptor MaskoffType = PrototypeDescriptor(
1094
static_cast<uint8_t>(BaseTypeModifier::Vector),
1095
static_cast<uint8_t>(getTupleVTM(NF)),
1096
BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1097
NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1098
} else {
1099
// NF > 1 cases for segment load operations.
1100
// Convert
1101
// (void, op0 address, op1 address, ...)
1102
// to
1103
// (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
1104
PrototypeDescriptor MaskoffType = Prototype[1];
1105
MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1106
NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1107
}
1108
}
1109
}
1110
1111
// If HasVL, append PrototypeDescriptor:VL to last operand
1112
if (HasVL)
1113
NewPrototype.push_back(PrototypeDescriptor::VL);
1114
1115
return NewPrototype;
1116
}
1117
1118
llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
1119
return {Policy(Policy::PolicyType::Undisturbed)}; // TU
1120
}
1121
1122
llvm::SmallVector<Policy>
1123
RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
1124
bool HasMaskPolicy) {
1125
if (HasTailPolicy && HasMaskPolicy)
1126
return {Policy(Policy::PolicyType::Undisturbed,
1127
Policy::PolicyType::Agnostic), // TUM
1128
Policy(Policy::PolicyType::Undisturbed,
1129
Policy::PolicyType::Undisturbed), // TUMU
1130
Policy(Policy::PolicyType::Agnostic,
1131
Policy::PolicyType::Undisturbed)}; // MU
1132
if (HasTailPolicy && !HasMaskPolicy)
1133
return {Policy(Policy::PolicyType::Undisturbed,
1134
Policy::PolicyType::Agnostic)}; // TU
1135
if (!HasTailPolicy && HasMaskPolicy)
1136
return {Policy(Policy::PolicyType::Agnostic,
1137
Policy::PolicyType::Undisturbed)}; // MU
1138
llvm_unreachable("An RVV instruction should not be without both tail policy "
1139
"and mask policy");
1140
}
1141
1142
void RVVIntrinsic::updateNamesAndPolicy(
1143
bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
1144
std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
1145
1146
auto appendPolicySuffix = [&](const std::string &suffix) {
1147
Name += suffix;
1148
BuiltinName += suffix;
1149
OverloadedName += suffix;
1150
};
1151
1152
if (HasFRMRoundModeOp) {
1153
Name += "_rm";
1154
BuiltinName += "_rm";
1155
}
1156
1157
if (IsMasked) {
1158
if (PolicyAttrs.isTUMUPolicy())
1159
appendPolicySuffix("_tumu");
1160
else if (PolicyAttrs.isTUMAPolicy())
1161
appendPolicySuffix("_tum");
1162
else if (PolicyAttrs.isTAMUPolicy())
1163
appendPolicySuffix("_mu");
1164
else if (PolicyAttrs.isTAMAPolicy()) {
1165
Name += "_m";
1166
BuiltinName += "_m";
1167
} else
1168
llvm_unreachable("Unhandled policy condition");
1169
} else {
1170
if (PolicyAttrs.isTUPolicy())
1171
appendPolicySuffix("_tu");
1172
else if (PolicyAttrs.isTAPolicy()) // no suffix needed
1173
return;
1174
else
1175
llvm_unreachable("Unhandled policy condition");
1176
}
1177
}
1178
1179
SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
1180
SmallVector<PrototypeDescriptor> PrototypeDescriptors;
1181
const StringRef Primaries("evwqom0ztulf");
1182
while (!Prototypes.empty()) {
1183
size_t Idx = 0;
1184
// Skip over complex prototype because it could contain primitive type
1185
// character.
1186
if (Prototypes[0] == '(')
1187
Idx = Prototypes.find_first_of(')');
1188
Idx = Prototypes.find_first_of(Primaries, Idx);
1189
assert(Idx != StringRef::npos);
1190
auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
1191
Prototypes.slice(0, Idx + 1));
1192
if (!PD)
1193
llvm_unreachable("Error during parsing prototype.");
1194
PrototypeDescriptors.push_back(*PD);
1195
Prototypes = Prototypes.drop_front(Idx + 1);
1196
}
1197
return PrototypeDescriptors;
1198
}
1199
1200
raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
1201
OS << "{";
1202
OS << "\"" << Record.Name << "\",";
1203
if (Record.OverloadedName == nullptr ||
1204
StringRef(Record.OverloadedName).empty())
1205
OS << "nullptr,";
1206
else
1207
OS << "\"" << Record.OverloadedName << "\",";
1208
OS << Record.PrototypeIndex << ",";
1209
OS << Record.SuffixIndex << ",";
1210
OS << Record.OverloadedSuffixIndex << ",";
1211
OS << (int)Record.PrototypeLength << ",";
1212
OS << (int)Record.SuffixLength << ",";
1213
OS << (int)Record.OverloadedSuffixSize << ",";
1214
OS << Record.RequiredExtensions << ",";
1215
OS << (int)Record.TypeRangeMask << ",";
1216
OS << (int)Record.Log2LMULMask << ",";
1217
OS << (int)Record.NF << ",";
1218
OS << (int)Record.HasMasked << ",";
1219
OS << (int)Record.HasVL << ",";
1220
OS << (int)Record.HasMaskedOffOperand << ",";
1221
OS << (int)Record.HasTailPolicy << ",";
1222
OS << (int)Record.HasMaskPolicy << ",";
1223
OS << (int)Record.HasFRMRoundModeOp << ",";
1224
OS << (int)Record.IsTuple << ",";
1225
OS << (int)Record.UnMaskedPolicyScheme << ",";
1226
OS << (int)Record.MaskedPolicyScheme << ",";
1227
OS << "},\n";
1228
return OS;
1229
}
1230
1231
} // end namespace RISCV
1232
} // end namespace clang
1233
1234