MLIR 24.0.0git
TosaProfileCompliance.cpp
Go to the documentation of this file.
1//===--- TosaProfileCompliance.cpp - Tosa Profile Compliance Validation ---===//
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
10#include "llvm/ADT/StringExtras.h"
11#include "llvm/Support/Compiler.h"
12#include "llvm/Support/raw_ostream.h"
13
14using namespace mlir;
15using namespace mlir::tosa;
16
18 const TypeInfo boolT = {mlir::IntegerType::getTypeID(), 1};
19 const TypeInfo i4T = {mlir::IntegerType::getTypeID(), 4};
20 const TypeInfo i8T = {mlir::IntegerType::getTypeID(), 8};
21 const TypeInfo i16T = {mlir::IntegerType::getTypeID(), 16};
22 const TypeInfo i32T = {mlir::IntegerType::getTypeID(), 32};
23 const TypeInfo i48T = {mlir::IntegerType::getTypeID(), 48};
24 const TypeInfo i64T = {mlir::IntegerType::getTypeID(), 64};
25 const TypeInfo bf16T = {mlir::BFloat16Type::getTypeID(), 16};
26 const TypeInfo fp16T = {mlir::Float16Type::getTypeID(), 16};
27 const TypeInfo fp32T = {mlir::Float32Type::getTypeID(), 32};
28 const TypeInfo fp8e4m3T = {mlir::Float8E4M3FNType::getTypeID(), 8};
29 const TypeInfo fp8e5m2T = {mlir::Float8E5M2Type::getTypeID(), 8};
30
31 // micro-scaling formats
32 // Note: these types exist to suppport the deprecated block_scaled operations
33 // and can be removed once those operations are removed.
34 const TypeInfo fp6e2m3T = {mlir::Float6E2M3FNType::getTypeID(), 6};
35 const TypeInfo fp6e3m2T = {mlir::Float6E3M2FNType::getTypeID(), 6};
36 const TypeInfo fp4e2m1T = {mlir::Float4E2M1FNType::getTypeID(), 4};
37 const TypeInfo fp8ue8m0T = {mlir::Float8E8M0FNUType::getTypeID(), 8};
38 const TypeInfo mxint8T = {mlir::tosa::mxint8Type::getTypeID(), 8};
39
40 // Block scaled formats
41 const TypeID blockScaledID = mlir::tosa::BlockScaledType::getTypeID();
42 const TypeID fp4e2m1ID = mlir::Float4E2M1FNType::getTypeID();
43 const TypeID fp6e2m3ID = mlir::Float6E2M3FNType::getTypeID();
44 const TypeID fp6e3m2ID = mlir::Float6E3M2FNType::getTypeID();
45 const TypeID fp8e4m3ID = mlir::Float8E4M3FNType::getTypeID();
46 const TypeID fp8e5m2ID = mlir::Float8E5M2Type::getTypeID();
47 const TypeID fp8ue8m0ID = mlir::Float8E8M0FNUType::getTypeID();
48 const TypeID mxint8ID = mlir::tosa::mxint8Type::getTypeID();
49
50 const TypeInfo bs32_fp8ue8m0_fp4e2m1T = {blockScaledID, 4, fp4e2m1ID,
51 fp8ue8m0ID,
52 tosa::BlockShape::BLOCK_SHAPE_32};
53 const TypeInfo bs32_fp8ue8m0_fp6e2m3T = {blockScaledID, 6, fp6e2m3ID,
54 fp8ue8m0ID,
55 tosa::BlockShape::BLOCK_SHAPE_32};
56 const TypeInfo bs32_fp8ue8m0_fp6e3m2T = {blockScaledID, 6, fp6e3m2ID,
57 fp8ue8m0ID,
58 tosa::BlockShape::BLOCK_SHAPE_32};
59 const TypeInfo bs32_fp8ue8m0_fp8e4m3T = {blockScaledID, 8, fp8e4m3ID,
60 fp8ue8m0ID,
61 tosa::BlockShape::BLOCK_SHAPE_32};
62 const TypeInfo bs32_fp8ue8m0_fp8e5m2T = {blockScaledID, 8, fp8e5m2ID,
63 fp8ue8m0ID,
64 tosa::BlockShape::BLOCK_SHAPE_32};
65 const TypeInfo bs32_fp8ue8m0_mxint8T = {
66 blockScaledID, 8, mxint8ID, fp8ue8m0ID, tosa::BlockShape::BLOCK_SHAPE_32};
67
68// The profile-based compliance content below is auto-generated by a script
69// in https://github.com/arm/tosa-specification
71 // End of auto-generated metadata
72}
73
74template <>
78
79template <>
82 return extensionComplianceMap;
83}
84
85// Base populating function
86LogicalResult ProfileInfoDepot::populateProfileInfo(ValueRange operands,
87 ValueRange results) {
88 for (const auto &operand : operands)
89 addValue(operand);
90 for (const auto &result : results)
92 return success();
93}
94
95template <>
96LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ConcatOp op) {
97 addValue(op.getInput1().front());
98 addValue(op.getOutput());
99 return success();
100}
101
102template <>
103LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::AvgPool2dOp op) {
104 addValue(op.getInput());
105 addValue(op.getInputZp());
106 addValue(op.getOutputZp());
107 addType(op.getAccType());
108 addValue(op.getOutput());
109 return success();
110}
111
112template <>
113LogicalResult
114ProfileInfoDepot::populateProfileInfo(tosa::AvgPool2dAdaptiveOp op) {
115 addValue(op.getInput());
116 addValue(op.getInputZp());
117 addValue(op.getOutputZp());
118 addType(op.getAccType());
119 addValue(op.getOutput());
120 return success();
121}
122
123template <>
124LogicalResult
125ProfileInfoDepot::populateProfileInfo(tosa::MaxPool2dAdaptiveOp op) {
126 addValue(op.getInput());
127 addValue(op.getOutput());
128 return success();
129}
130
131template <typename T>
132LogicalResult ProfileInfoDepot::populateProfileInfoConv(T op) {
133 addValue(op.getInput());
134 addValue(op.getWeight());
135 addValue(op.getBias());
136 addValue(op.getInputZp());
137 addValue(op.getWeightZp());
138 addType(op.getAccType());
139 addValue(op.getOutput());
140 return success();
141}
142
143template <>
144LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::Conv2DOp op) {
145 return populateProfileInfoConv(op);
146}
147
148template <>
149LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::Conv3DOp op) {
150 return populateProfileInfoConv(op);
151}
152
153template <>
154LogicalResult
155ProfileInfoDepot::populateProfileInfo(tosa::TransposeConv2DOp op) {
156 return populateProfileInfoConv(op);
157}
158
159template <>
160LogicalResult
161ProfileInfoDepot::populateProfileInfo(tosa::DepthwiseConv2DOp op) {
162 return populateProfileInfoConv(op);
163}
164
165template <>
166LogicalResult
167ProfileInfoDepot::populateProfileInfo(tosa::Conv2DBlockScaledOp op) {
168 addValue(op.getInputData());
169 addValue(op.getInputScale());
170 addValue(op.getWeightData());
171 addValue(op.getWeightScale());
172 addValue(op.getBias());
173 addValue(op.getOutput());
174 return success();
175}
176
177template <>
178LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::PadOp op) {
179 addValue(op.getInput1());
180 addValue(op.getPadConst());
181 addValue(op.getOutput());
182 return success();
183}
184
185template <typename T>
186LogicalResult ProfileInfoDepot::populateProfileInfoDataLayout(T op) {
187 addValue(op.getInput1());
188 addValue(op.getOutput());
189 return success();
190}
191
192template <>
193LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ReshapeOp op) {
194 return populateProfileInfoDataLayout(op);
195}
196
197template <>
198LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::SliceOp op) {
199 return populateProfileInfoDataLayout(op);
200}
201
202template <>
203LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::TileOp op) {
204 return populateProfileInfoDataLayout(op);
205}
206
207template <>
208LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::TransposeOp op) {
209 return populateProfileInfoDataLayout(op);
210}
211
212template <>
213LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::GatherOp op) {
214 addValue(op.getValues());
215 addValue(op.getIndices());
216 addValue(op.getOutput());
217 return success();
218}
219
220template <>
221LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::RowGatherOp op) {
222 addValue(op.getValues());
223 addValue(op.getIndices());
224 addValue(op.getOutput());
225 return success();
226}
227
228template <>
229LogicalResult
230ProfileInfoDepot::populateProfileInfo(tosa::RowGatherBlockScaledOp op) {
231 for (Value value : op.getValues())
232 addValue(value);
233 addValue(op.getIndices());
234 addValue(op.getRowCount());
235 for (Value result : op.getOutput())
237 return success();
238}
239
240template <>
241LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ScatterOp op) {
242 addValue(op.getValuesIn());
243 addValue(op.getIndices());
244 addValue(op.getInput());
245 addValue(op.getValuesOut());
246 return success();
247}
248
249template <>
250LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MulOp op) {
251 addValue(op.getInput1());
252 addValue(op.getInput2());
253 addValue(op.getOutput());
254 return success();
255}
256
257template <>
258LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ResizeOp op) {
259 addValue(op.getInput());
260 addValue(op.getOutput());
261 return success();
262}
263
264template <>
265LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::SelectOp op) {
266 addValue(op.getOnTrue());
267 addValue(op.getOnFalse());
268 addValue(op.getOutput());
269 return success();
270}
271
272template <>
273LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::RescaleOp op) {
274 addValue(op.getInput());
275 addValue(op.getInputZp());
276 addValue(op.getOutputZp());
277 addValue(op.getOutput());
278 return success();
279}
280
281template <>
282LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MatMulOp op) {
283 addValue(op.getA());
284 addValue(op.getB());
285 addValue(op.getAZp());
286 addValue(op.getBZp());
287 addValue(op.getOutput());
288 return success();
289}
290
291template <>
292LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MatMulTOp op) {
293 addValue(op.getA());
294 addValue(op.getB());
295 addValue(op.getAZp());
296 addValue(op.getBZp());
297 addValue(op.getOutput());
298 return success();
299}
300
301template <>
302LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableOp op) {
303 addType(op.getType());
304 return success();
305}
306
307template <>
308LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableWriteOp op) {
309 addValue(op.getInput1());
310 return success();
311}
312
313template <>
314LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::DimOp op) {
315 addValue(op.getInput1());
316 return success();
317}
318
319LogicalResult ProfileInfoDepot::populatationDispatch(Operation *op) {
320// This helper function only populates the info for the customised operands.
321#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp) \
322 if (isa<tosa::tosaOp##Op>(op)) { \
323 return populateProfileInfo(cast<tosa::tosaOp##Op>(op)); \
324 }
325
326#define POPULATE_PROFILE_INFO_SKIP(tosaOp) \
327 if (isa<tosa::tosaOp##Op>(op)) \
328 return success();
329
330// This helper function populates the info for all operands.
331#define POPULATE_PROFILE_INFO_COMMON(tosaOp) \
332 if (isa<tosa::tosaOp##Op>(op)) { \
333 return populateProfileInfo(op->getOperands(), op->getResults()); \
334 }
335
336 // Skip irrelevant operands when they are independent and not tied to any
337 // specific profile/extension.
339 POPULATE_PROFILE_INFO_CUSTOM(AvgPool2dAdaptive)
340 POPULATE_PROFILE_INFO_CUSTOM(TransposeConv2D)
342 POPULATE_PROFILE_INFO_CUSTOM(Conv2DBlockScaled)
344 POPULATE_PROFILE_INFO_CUSTOM(DepthwiseConv2D)
354 POPULATE_PROFILE_INFO_CUSTOM(RowGatherBlockScaled)
362 POPULATE_PROFILE_INFO_CUSTOM(VariableWrite)
364 POPULATE_PROFILE_INFO_CUSTOM(MaxPool2dAdaptive)
365
366 // For the most of tosa operators, all operands are profile/extension related
367 // and hence are all considered in this profile-based compilance check.
368 POPULATE_PROFILE_INFO_COMMON(MatmulTBlockScaled)
372 POPULATE_PROFILE_INFO_COMMON(CastFromBlockScaled)
373 POPULATE_PROFILE_INFO_COMMON(CastToBlockScaled)
385 POPULATE_PROFILE_INFO_COMMON(ArithmeticRightShift)
390 POPULATE_PROFILE_INFO_COMMON(LogicalLeftShift)
391 POPULATE_PROFILE_INFO_COMMON(LogicalRightShift)
414 POPULATE_PROFILE_INFO_COMMON(ReduceProduct)
417 POPULATE_PROFILE_INFO_COMMON(GreaterEqual)
421 POPULATE_PROFILE_INFO_COMMON(VariableRead)
422
423 // Type Invariant Extension, a capability extension that is independent
424 // of the data type, meaning any compatible type can be used. No type
425 // constraint for those operations.
427 POPULATE_PROFILE_INFO_SKIP(AssertEqualShape)
428 POPULATE_PROFILE_INFO_SKIP(ConcatShape)
430 POPULATE_PROFILE_INFO_SKIP(DivCeilShape)
431 POPULATE_PROFILE_INFO_SKIP(DivFloorShape)
433 POPULATE_PROFILE_INFO_SKIP(Log2CeilShape)
434 POPULATE_PROFILE_INFO_SKIP(Log2FloorShape)
444
445 return failure();
446}
447
448//===----------------------------------------------------------------------===//
449// Tosa Profile And Extension Compliance Checker
450//===----------------------------------------------------------------------===//
451
452template <typename T>
453FailureOr<SmallVector<OpComplianceInfo<T>>>
454TosaProfileCompliance::getOperatorMatchedEntries(Operation *op) {
455 const std::string opName = op->getName().getStringRef().str();
456 const auto complianceMap = getProfileComplianceMap<T>();
457 const auto it = complianceMap.find(opName);
458 if (it == complianceMap.end())
459 return {};
460
461 return findMatchedEntries<T>(op, it->second);
462}
463
464template <typename T>
466 Operation *op, const tosa::TargetEnv &targetEnv) {
467 const auto maybeOpEntries = getOperatorMatchedEntries<T>(op);
468 if (failed(maybeOpEntries))
469 return success();
470
471 const auto opEntries = maybeOpEntries.value();
472 if (opEntries.size() == 0) {
473 // No matched restriction found.
474 return success();
475 }
476
477 // Check the profile/extension requirement according to the current target
478 // profiles/extensions.
479 const auto isModeAllowed = [&](const OpComplianceInfo<T> &info) -> bool {
480 if (info.condition == CheckCondition::allOf)
481 return targetEnv.allowsAllOf(info.mode);
482 return targetEnv.allowsAnyOf(info.mode);
483 };
484
485 // Check the matched op compliance version does not exceed the target
486 // specification version.
487 const TosaSpecificationVersion targetVersion{targetEnv.getSpecVersion()};
488 const auto isVersionCompatible =
489 [&targetVersion](const OpComplianceInfo<T> &info) -> bool {
490 // Assume compatible if there are no versioned type constraints
491 if (info.operandTypeInfoSet.empty())
492 return true;
493 const TosaSpecificationVersion complianceVersion{
494 info.operandTypeInfoSet.front().second};
495 return targetVersion.isBackwardsCompatibleWith(complianceVersion);
496 };
497
498 for (const auto &info : opEntries) {
499 // Type constraints exist, check if they are compatible with the current
500 // target definition, including: profile, extension and specification
501 // version
502 if (isModeAllowed(info) && isVersionCompatible(info))
503 return success();
504 }
505
506 // No valid entry was found, now emit appropriate error message and return
507 // failure
508 std::string message;
509 llvm::raw_string_ostream os(message);
510
511 os << "illegal: ";
512 const size_t numOpEntries = opEntries.size();
513 for (const auto &[index, info] : llvm::enumerate(opEntries)) {
514 bool mismatchedVersion = false;
515 if (!isVersionCompatible(info)) {
516 mismatchedVersion = true;
517 os << "requires specification version compatible with "
518 << stringifyVersion(info.operandTypeInfoSet.front().second) << " (got "
519 << stringifyVersion(targetVersion) << ") ";
520 }
521
522 if (!isModeAllowed(info)) {
523 if (mismatchedVersion)
524 os << "and ";
525 os << "requires "
526 << (info.condition == CheckCondition::allOf ? "all of " : "any of ")
527 << "[" << llvm::join(stringifyProfile<T>(info.mode), ", ")
528 << "] profiles/extensions ";
529 }
530
531 if (index != numOpEntries - 1)
532 os << "OR ";
533 }
534 os << "to be specified in the target environment";
535
536 return op->emitOpError(message);
537}
538
539LogicalResult
541 const tosa::TargetEnv &targetEnv) {
542 return checkProfileOrExtension<Profile>(op, targetEnv);
543}
544
545LogicalResult
550
552 const auto maybeProfEntries = getOperatorMatchedEntries<Profile>(op);
553 const auto maybeExtEntries = getOperatorMatchedEntries<Extension>(op);
554 if (failed(maybeProfEntries) && failed(maybeExtEntries))
555 return success();
556
557 const bool hasEntry =
558 (succeeded(maybeProfEntries) && !maybeProfEntries.value().empty()) ||
559 (succeeded(maybeExtEntries) && !maybeExtEntries.value().empty());
560
561 if (!hasEntry) {
562 std::string message;
563 llvm::raw_string_ostream os(message);
564 os << "illegal: operation operand/result data types did not align with any "
565 "profile or extension, got (";
566
567 ProfileInfoDepot depot(op);
568 SmallVector<TypeInfo> current = depot.getInfo();
569 for (const auto &typeInfo : llvm::drop_end(current))
570 os << stringifyTypeInfo(typeInfo) << ",";
571 os << stringifyTypeInfo(current.back()) << ")";
572
573 // avoid polluting the error message output by outputting only
574 // the best match
575 const std::string opName = op->getName().getStringRef().str();
576 int maxMatches = -1;
577 SmallVector<TypeInfo> bestTypeInfo;
578 const auto searchBestMatch = [&](auto map) {
579 for (const auto &complianceInfos : map[opName]) {
580 for (const auto &versionedTypeInfos :
581 complianceInfos.operandTypeInfoSet) {
582 const SmallVector<TypeInfo> typeInfos = versionedTypeInfos.first;
583 if (current.size() != typeInfos.size())
584 continue;
585 const int matches = llvm::count_if(
586 llvm::zip_equal(current, typeInfos), [&](const auto zipType) {
587 return isSameTypeInfo(std::get<0>(zipType),
588 std::get<1>(zipType));
589 });
590 if (matches > maxMatches) {
591 maxMatches = matches;
592 bestTypeInfo = typeInfos;
593 }
594 }
595 }
596 };
597 searchBestMatch(getProfileComplianceMap<Profile>());
598 searchBestMatch(getProfileComplianceMap<Extension>());
599
600 os << ", did you mean (";
601 for (const auto &typeInfo : llvm::drop_end(bestTypeInfo))
602 os << stringifyTypeInfo(typeInfo) << ",";
603 os << stringifyTypeInfo(bestTypeInfo.back()) << ")? ";
604 os << "Otherwise, please refer to the 'supported data types' for '"
605 << opName << "' in the specification.";
606 op->emitOpError(message);
607 return failure();
608 }
609
610 return success();
611}
612
613// Find the profiles or extensions requirement according to the signature of
614// type of the operand list.
615template <typename T>
618 assert(compInfo.size() != 0 &&
619 "profile-based compliance information is empty");
620
621 // If there are no type constraints for the given operation, return the
622 // matched entries directly so required profile/extension information can
623 // be checked
625 if (llvm::all_of(compInfo, [&matchedInfos](const OpComplianceInfo<T> &info) {
626 if (info.operandTypeInfoSet.empty()) {
627 matchedInfos.push_back(info);
628 return true;
629 }
630 return false;
631 }))
632 return matchedInfos;
633
634 // Get the type information of the operator we're trying to match
635 ProfileInfoDepot depot(op);
636 SmallVector<TypeInfo> present = depot.getInfo();
637 if (present.size() == 0)
638 return {};
639
640 // Compare 'present' against known type signatures in the compliance metadata
641 for (size_t i = 0; i < compInfo.size(); i++) {
642 SmallVector<VersionedTypeInfo> sets = compInfo[i].operandTypeInfoSet;
643 for (const auto &set : sets) {
644 SmallVector<TypeInfo> expected = set.first;
645 // Tensor-list operators can legitimately have multiple valid signatures
646 // with different operand/result counts, e.g. data-only and data+scale
647 // forms. Treat those as non-matches instead of asserting.
648 if (present.size() != expected.size())
649 continue;
650
651 bool isFound = true;
652 // Compare the type signature between the given operation and the
653 // compliance metadata.
654 for (size_t j = 0; j < expected.size(); j++) {
655 if (!isSameTypeInfo(present[j], expected[j])) {
656 // Verify the next mode set from the list.
657 isFound = false;
658 break;
659 }
660 }
661
662 if (isFound == true) {
663 SmallVector<VersionedTypeInfo> typeInfoSet{set};
664 OpComplianceInfo<T> info{compInfo[i].mode, typeInfoSet,
665 compInfo[i].condition};
666 matchedInfos.push_back(info);
667 }
668 }
669 }
670
671 return matchedInfos;
672}
673
674// Debug utilites.
675template <typename T>
678 SmallVector<StringRef> debugStrings;
679 for (const auto &profile : profiles) {
680 if constexpr (std::is_same_v<T, Profile>)
681 debugStrings.push_back(tosa::stringifyProfile(profile));
682 else
683 debugStrings.push_back(tosa::stringifyExtension(profile));
684 }
685 return debugStrings;
686}
687
688template <typename T>
690 const SmallVector<ArrayRef<T>> &profileSet) {
691 SmallVector<StringRef> debugStrings;
692
693 for (const auto &profiles : profileSet) {
694 auto tempStrings = stringifyProfile<T>(profiles);
695 llvm::append_range(debugStrings, tempStrings);
696 }
697
698 return debugStrings;
699}
700
703 const auto stringifyScalarTypeInfo =
704 [](const TypeInfo &typeInfo) -> llvm::SmallString<32> {
705 if (typeInfo.typeID == mlir::IntegerType::getTypeID()) {
706 return {"i" + llvm::utostr(typeInfo.bitWidth)};
707 }
708 if (typeInfo.typeID == mlir::Float16Type::getTypeID()) {
709 return {"f16"};
710 } else if (typeInfo.typeID == mlir::Float32Type::getTypeID()) {
711 return {"f32"};
712 } else if (typeInfo.typeID == mlir::BFloat16Type::getTypeID()) {
713 return {"bf16"};
714 } else if (typeInfo.typeID == mlir::Float8E4M3FNType::getTypeID()) {
715 return {"fp8e4m3"};
716 } else if (typeInfo.typeID == mlir::Float8E5M2Type::getTypeID()) {
717 return {"fp8e5m2"};
718 } else if (typeInfo.typeID == mlir::Float6E2M3FNType::getTypeID()) {
719 return {"fp6e2m3"};
720 } else if (typeInfo.typeID == mlir::Float6E3M2FNType::getTypeID()) {
721 return {"fp6e3m2"};
722 } else if (typeInfo.typeID == mlir::Float4E2M1FNType::getTypeID()) {
723 return {"fp4e2m1"};
724 } else if (typeInfo.typeID == mlir::Float8E8M0FNUType::getTypeID()) {
725 return {"fp8e8m0"};
726 } else if (typeInfo.typeID == tosa::mxint8Type::getTypeID()) {
727 return {"mxint8"};
728 }
729 llvm_unreachable("unknown type");
730 };
731
732 if (typeInfo.typeID == tosa::BlockScaledType::getTypeID()) {
733 TypeInfo valueInfo = {typeInfo.valueTypeID, typeInfo.bitWidth};
734 TypeInfo scaleInfo = {typeInfo.scaleTypeID, 8};
736 llvm::raw_svector_ostream os(result);
737 os << "bs"
738 << tosa::BlockShapeAttr::getBlockShapeValue(typeInfo.blockShape.value())
739 << "_" << stringifyScalarTypeInfo(scaleInfo) << "_"
740 << stringifyScalarTypeInfo(valueInfo);
741 return result;
742 }
743
744 return stringifyScalarTypeInfo(typeInfo);
745}
return success()
#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp)
#define POPULATE_PROFILE_INFO_COMMON(tosaOp)
#define POPULATE_PROFILE_INFO_SKIP(tosaOp)
std::unordered_map< std::string, SmallVector< OpComplianceInfo< Profile > > > OperationProfileComplianceMap
std::unordered_map< std::string, SmallVector< OpComplianceInfo< Extension > > > OperationExtensionComplianceMap
@ Gather
SmallVector< TypeInfo > getInfo()
bool isSameTypeInfo(TypeInfo a, TypeInfo b)
LogicalResult checkProfile(Operation *op, const tosa::TargetEnv &targetEnv)
static llvm::SmallString< 32 > stringifyTypeInfo(const TypeInfo &typeInfo)
LogicalResult checkExtension(Operation *op, const tosa::TargetEnv &targetEnv)
LogicalResult checkInvalid(Operation *op)
SmallVector< StringRef > stringifyProfile(ArrayRef< T > profiles)
std::unordered_map< std::string, SmallVector< OpComplianceInfo< T > > > getProfileComplianceMap()
SmallVector< OpComplianceInfo< T > > findMatchedEntries(Operation *op, SmallVector< OpComplianceInfo< T > > compInfo)
LogicalResult checkProfileOrExtension(Operation *op, const tosa::TargetEnv &targetEnv)
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OperationName getName()
The name of an operation is the key identifier for it.
Definition Operation.h:115
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
This class represents the capability enabled in the target implementation such as profile,...
Definition TargetEnv.h:119
bool allowsAllOf(ArrayRef< Profile > profs) const
Definition TargetEnv.h:145
bool allowsAnyOf(ArrayRef< Profile > profs) const
Definition TargetEnv.h:141
TosaSpecificationVersion getSpecVersion() const
Definition TargetEnv.h:132
A thin wrapper around the SpecificationVersion enum to represent and provide utilities around the TOS...
Definition TargetEnv.h:60
bool isBackwardsCompatibleWith(TosaSpecificationVersion baseVersion) const
Definition TargetEnv.h:69
llvm::SmallString< 4 > stringifyVersion(TosaSpecificationVersion version)
Definition TargetEnv.cpp:25
Include the generated interface declarations.
@ Mul
RHS of mul is always a constant or a symbolic expression.
Definition AffineExpr.h:43
SmallVector< VersionedTypeInfo > operandTypeInfoSet
mlir::TypeID valueTypeID
mlir::TypeID scaleTypeID
std::optional< tosa::BlockShape > blockShape
mlir::TypeID typeID
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.