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