31#include "llvm/ADT/APFloat.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/MapVector.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/ScopeExit.h"
37#include "llvm/ADT/ScopedHashTable.h"
38#include "llvm/ADT/SetVector.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/ADT/StringSet.h"
41#include "llvm/ADT/TypeSwitch.h"
42#include "llvm/Support/CommandLine.h"
43#include "llvm/Support/DebugLog.h"
44#include "llvm/Support/Endian.h"
45#include "llvm/Support/ManagedStatic.h"
46#include "llvm/Support/Regex.h"
47#include "llvm/Support/SaveAndRestore.h"
48#include "llvm/Support/Threading.h"
49#include "llvm/Support/raw_ostream.h"
58#define DEBUG_TYPE "mlir-asm-printer"
99 *this << (operand ? operand.getType() : Type());
115 *this << (result ? result.getType() : Type());
127#include "mlir/IR/OpAsmAttrInterface.cpp.inc"
128#include "mlir/IR/OpAsmOpInterface.cpp.inc"
129#include "mlir/IR/OpAsmTypeInterface.cpp.inc"
133 return entry.
emitError() <<
"unknown 'resource' key '" << entry.
getKey()
146struct AsmPrinterOptions {
147 llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
148 "mlir-print-elementsattrs-with-hex-if-larger",
150 "Print DenseElementsAttrs with a hex string that have "
151 "more elements than the given upper limit (use -1 to disable)")};
153 llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
154 "mlir-elide-elementsattrs-if-larger",
155 llvm::cl::desc(
"Elide ElementsAttrs with \"...\" that have "
156 "more elements than the given upper limit")};
158 llvm::cl::opt<unsigned> elideResourceStringsIfLarger{
159 "mlir-elide-resource-strings-if-larger",
161 "Elide printing value of resources if string is too long in chars.")};
163 llvm::cl::opt<bool> printDebugInfoOpt{
164 "mlir-print-debuginfo", llvm::cl::init(
false),
165 llvm::cl::desc(
"Print debug info in MLIR output")};
167 llvm::cl::opt<bool> printPrettyDebugInfoOpt{
168 "mlir-pretty-debuginfo", llvm::cl::init(
false),
169 llvm::cl::desc(
"Print pretty debug info in MLIR output")};
173 llvm::cl::opt<bool> printGenericOpFormOpt{
174 "mlir-print-op-generic", llvm::cl::init(
false),
175 llvm::cl::desc(
"Print the generic op form"), llvm::cl::Hidden};
177 llvm::cl::opt<bool> assumeVerifiedOpt{
178 "mlir-print-assume-verified", llvm::cl::init(
false),
179 llvm::cl::desc(
"Skip op verification when using custom printers"),
182 llvm::cl::opt<bool> printLocalScopeOpt{
183 "mlir-print-local-scope", llvm::cl::init(
false),
184 llvm::cl::desc(
"Print with local scope and inline information (eliding "
185 "aliases for attributes, types, and locations)")};
187 llvm::cl::opt<bool> skipRegionsOpt{
188 "mlir-print-skip-regions", llvm::cl::init(
false),
189 llvm::cl::desc(
"Skip regions when printing ops.")};
191 llvm::cl::opt<bool> printValueUsers{
192 "mlir-print-value-users", llvm::cl::init(
false),
194 "Print users of operation results and block arguments as a comment")};
196 llvm::cl::opt<bool> printUniqueSSAIDs{
197 "mlir-print-unique-ssa-ids", llvm::cl::init(
false),
198 llvm::cl::desc(
"Print unique SSA ID numbers for values, block arguments "
199 "and naming conflicts across all regions")};
201 llvm::cl::opt<bool> useNameLocAsPrefix{
202 "mlir-use-nameloc-as-prefix", llvm::cl::init(
false),
203 llvm::cl::desc(
"Print SSA IDs using NameLocs as prefixes")};
218 : printDebugInfoFlag(
false), printDebugInfoPrettyFormFlag(
false),
219 printGenericOpFormFlag(
false), skipRegionsFlag(
false),
220 assumeVerifiedFlag(
false), printLocalScope(
false),
221 printValueUsersFlag(
false), printUniqueSSAIDsFlag(
false),
222 useNameLocAsPrefix(
false) {
226 if (
clOptions->elideElementsAttrIfLarger.getNumOccurrences())
227 elementsAttrElementLimit =
clOptions->elideElementsAttrIfLarger;
228 if (
clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences())
229 elementsAttrHexElementLimit =
230 clOptions->printElementsAttrWithHexIfLarger.getValue();
231 if (
clOptions->elideResourceStringsIfLarger.getNumOccurrences())
232 resourceStringCharLimit =
clOptions->elideResourceStringsIfLarger;
233 printDebugInfoFlag =
clOptions->printDebugInfoOpt;
234 printDebugInfoPrettyFormFlag =
clOptions->printPrettyDebugInfoOpt;
235 printGenericOpFormFlag =
clOptions->printGenericOpFormOpt;
236 assumeVerifiedFlag =
clOptions->assumeVerifiedOpt;
237 printLocalScope =
clOptions->printLocalScopeOpt;
238 skipRegionsFlag =
clOptions->skipRegionsOpt;
239 printValueUsersFlag =
clOptions->printValueUsers;
240 printUniqueSSAIDsFlag =
clOptions->printUniqueSSAIDs;
241 useNameLocAsPrefix =
clOptions->useNameLocAsPrefix;
250 elementsAttrElementLimit = largeElementLimit;
256 elementsAttrHexElementLimit = largeElementLimit;
262 resourceStringCharLimit = largeResourceLimit;
270 printDebugInfoFlag = enable;
271 printDebugInfoPrettyFormFlag = prettyForm;
277 printGenericOpFormFlag = enable;
283 skipRegionsFlag = skip;
289 assumeVerifiedFlag = enable;
297 printLocalScope = enable;
303 printValueUsersFlag = enable;
310 printUniqueSSAIDsFlag = enable;
316 return elementsAttrElementLimit &&
317 *elementsAttrElementLimit <
int64_t(attr.getNumElements()) &&
318 !llvm::isa<SplatElementsAttr>(attr);
324 return (elementsAttrHexElementLimit != -1) &&
325 (elementsAttrHexElementLimit <
int64_t(attr.getNumElements())) &&
326 !llvm::isa<SplatElementsAttr>(attr);
330 useNameLocAsPrefix = enable;
336 return elementsAttrElementLimit;
341 return elementsAttrHexElementLimit;
346 return resourceStringCharLimit;
351 return printDebugInfoFlag;
356 return printDebugInfoPrettyFormFlag;
361 return printGenericOpFormFlag;
369 return assumeVerifiedFlag;
377 return printValueUsersFlag;
387 return useNameLocAsPrefix;
398struct NewLineCounter {
399 unsigned curLine = 1;
421 template <
typename Container,
typename UnaryFunctor>
423 llvm::interleaveComma(c,
os, eachFn);
470 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
483 bool withKeyword =
false);
486 bool isTopLevel =
false);
522 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
546 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
548 : name(name), suffixIndex(suffixIndex), isType(isType),
549 isDeferrable(isDeferrable) {}
553 os << (isType ?
"!" :
"#") << name;
555 if (isdigit(name.back()))
562 bool isTypeAlias()
const {
return isType; }
565 bool canBeDeferred()
const {
return isDeferrable; }
571 uint32_t suffixIndex : 30;
575 bool isDeferrable : 1;
579 bool isPrinted =
false;
585class AliasInitializer {
588 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
589 llvm::BumpPtrAllocator &aliasAllocator)
590 : interfaces(interfaces), aliasAllocator(aliasAllocator),
591 aliasOS(aliasBuffer) {}
593 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
594 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
602 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
603 bool elideType =
false) {
604 return visitImpl(attr, aliases, canBeDeferred, elideType);
611 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
612 return visitImpl(type, aliases, canBeDeferred);
616 struct InProgressAliasInfo {
617 InProgressAliasInfo()
618 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
619 InProgressAliasInfo(StringRef alias)
620 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
624 if (aliasDepth !=
rhs.aliasDepth)
625 return aliasDepth <
rhs.aliasDepth;
626 if (isType !=
rhs.isType)
628 return alias <
rhs.alias;
633 std::optional<StringRef> alias;
636 unsigned aliasDepth : 30;
640 bool canBeDeferred : 1;
642 SmallVector<size_t> childIndices;
650 template <
typename T,
typename... PrintArgs>
651 std::pair<size_t, size_t>
653 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
654 bool canBeDeferred, PrintArgs &&...
printArgs);
657 void markAliasNonDeferrable(
size_t aliasIndex);
661 template <
typename T>
662 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
667 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
668 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
672 static void initializeAliases(
673 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
674 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
677 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
680 llvm::BumpPtrAllocator &aliasAllocator;
683 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
686 SmallString<32> aliasBuffer;
687 llvm::raw_svector_ostream aliasOS;
695class DummyAliasOperationPrinter :
private OpAsmPrinter {
697 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
698 AliasInitializer &initializer)
699 : printerFlags(printerFlags), initializer(initializer) {}
703 void printCustomOrGenericOp(Operation *op)
override {
705 if (printerFlags.shouldPrintDebugInfo())
706 initializer.visit(op->
getLoc(),
true);
709 if (!printerFlags.shouldPrintGenericOpForm()) {
720 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
722 if (!printerFlags.shouldSkipRegions()) {
735 for (
const NamedAttribute &attr : op->
getAttrs())
736 printAttribute(attr.getValue());
742 void print(
Block *block,
bool printBlockArgs =
true,
743 bool printBlockTerminator =
true) {
746 if (printBlockArgs) {
751 if (printerFlags.shouldPrintDebugInfo())
753 initializer.visit(arg.getLoc(),
false);
761 auto range = llvm::make_range(
763 std::prev(block->
end(),
764 (!hasTerminator || printBlockTerminator) ? 0 : 1));
765 for (Operation &op : range)
766 printCustomOrGenericOp(&op);
770 void printRegion(Region ®ion,
bool printEntryBlockArgs,
771 bool printBlockTerminators,
772 bool printEmptyBlock =
false)
override {
775 if (printerFlags.shouldSkipRegions()) {
780 auto *entryBlock = ®ion.
front();
781 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
782 for (
Block &
b : llvm::drop_begin(region, 1))
786 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
787 bool omitType)
override {
790 if (printerFlags.shouldPrintDebugInfo())
792 initializer.visit(arg.
getLoc(),
false);
796 void printType(Type type)
override { initializer.visit(type); }
799 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
800 void printAttributeWithoutType(Attribute attr)
override {
801 printAttribute(attr);
803 void printNamedAttribute(NamedAttribute attr)
override {
807 LogicalResult printAlias(Attribute attr)
override {
808 initializer.visit(attr);
811 LogicalResult printAlias(Type type)
override {
812 initializer.visit(type);
817 void printOptionalLocationSpecifier(Location loc)
override {
823 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
824 ArrayRef<StringRef> elidedAttrs = {})
override {
827 if (elidedAttrs.empty()) {
828 for (
const NamedAttribute &attr : attrs)
829 printAttribute(attr.getValue());
832 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
834 for (
const NamedAttribute &attr : attrs)
835 if (!elidedAttrsSet.contains(attr.getName().strref()))
836 printAttribute(attr.getValue());
838 void printOptionalAttrDictWithKeyword(
839 ArrayRef<NamedAttribute> attrs,
840 ArrayRef<StringRef> elidedAttrs = {})
override {
841 printOptionalAttrDict(attrs, elidedAttrs);
846 raw_ostream &getStream()
const override {
return os; }
850 void printFloat(
const APFloat &)
override {}
851 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
854 void increaseIndent()
override {}
855 void decreaseIndent()
override {}
856 void printOperand(Value)
override {}
857 void printOperand(Value, raw_ostream &os)
override {
865 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
866 void printSymbolName(StringRef)
override {}
867 void printSuccessor(
Block *)
override {}
869 void shadowRegionArgs(Region &,
ValueRange)
override {}
872 const OpPrintingFlags &printerFlags;
875 AliasInitializer &initializer;
878 mutable llvm::raw_null_ostream os;
883 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
885 SmallVectorImpl<size_t> &childIndices)
886 : initializer(initializer), canBeDeferred(canBeDeferred),
887 childIndices(childIndices) {}
892 template <
typename T,
typename... PrintArgs>
893 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
894 printAndVisitNestedAliasesImpl(value,
printArgs...);
895 return maxAliasDepth;
901 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
902 if (!isa<BuiltinDialect>(attr.
getDialect())) {
906 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
907 IntegerSetAttr, UnitAttr>(attr)) {
909 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
910 printAttribute(distinctAttr.getReferencedAttr());
911 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
912 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
913 printAttribute(nestedAttr.getName());
914 printAttribute(nestedAttr.getValue());
916 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
917 for (Attribute nestedAttr : arrayAttr.getValue())
918 printAttribute(nestedAttr);
919 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
921 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
922 printAttribute(locAttr.getFallbackLocation());
923 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
924 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
925 printAttribute(locAttr.getChildLoc());
926 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
927 printAttribute(locAttr.getCallee());
928 printAttribute(locAttr.getCaller());
929 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
930 if (Attribute metadata = locAttr.getMetadata())
931 printAttribute(metadata);
932 for (Location nestedLoc : locAttr.getLocations())
933 printAttribute(nestedLoc);
938 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
939 Type attrType = typedAttr.getType();
940 if (!llvm::isa<NoneType>(attrType))
945 void printAndVisitNestedAliasesImpl(Type type) {
950 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
952 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
953 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
954 printAttribute(memrefTy.getLayout());
955 if (memrefTy.getMemorySpace())
956 printAttribute(memrefTy.getMemorySpace());
961 auto visitFn = [&](
auto element) {
963 (void)printAlias(element);
970 recordAliasResult(initializer.visit(type, canBeDeferred));
974 void printAttribute(Attribute attr)
override {
975 recordAliasResult(initializer.visit(attr, canBeDeferred));
977 void printAttributeWithoutType(Attribute attr)
override {
979 initializer.visit(attr, canBeDeferred,
true));
981 void printNamedAttribute(NamedAttribute attr)
override {
985 LogicalResult printAlias(Attribute attr)
override {
986 printAttribute(attr);
989 LogicalResult printAlias(Type type)
override {
995 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
996 childIndices.push_back(aliasDepthAndIndex.second);
997 if (aliasDepthAndIndex.first > maxAliasDepth)
998 maxAliasDepth = aliasDepthAndIndex.first;
1003 raw_ostream &getStream()
const override {
return os; }
1007 void printFloat(
const APFloat &)
override {}
1010 void printSymbolName(StringRef)
override {}
1011 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1013 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1014 return success(cyclicPrintingStack.insert(opaquePointer));
1017 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1021 SetVector<const void *> cyclicPrintingStack;
1024 AliasInitializer &initializer;
1030 SmallVectorImpl<size_t> &childIndices;
1033 size_t maxAliasDepth = 0;
1036 mutable llvm::raw_null_ostream os;
1044 StringRef allowedPunctChars =
"$._-") {
1045 assert(!name.empty() &&
"Shouldn't have an empty name here");
1047 auto validChar = [&](
char ch) {
1048 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1051 auto copyNameToBuffer = [&] {
1052 for (
char ch : name) {
1054 buffer.push_back(ch);
1056 buffer.push_back(
'_');
1058 buffer.append(llvm::utohexstr((
unsigned char)ch));
1065 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1066 buffer.push_back(
'_');
1072 for (
char ch : name) {
1073 if (!validChar(ch)) {
1083unsigned AliasInitializer::uniqueAliasNameIndex(
1084 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1085 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1086 if (!usedAliases.count(alias)) {
1087 usedAliases.insert(alias);
1094 if (isdigit(alias.back()))
1095 probeAlias.push_back(
'_');
1097 if (nameCounts[probeAlias] == 0)
1098 nameCounts[probeAlias] = 1;
1102 unsigned nameIndex = nameCounts[probeAlias]++;
1103 probeAlias += llvm::utostr(nameIndex);
1104 if (!usedAliases.count(probeAlias)) {
1105 usedAliases.insert(probeAlias);
1109 probeAlias.resize(alias.size() + isdigit(alias.back()) ? 1 : 0);
1115void AliasInitializer::initializeAliases(
1116 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1117 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1119 unprocessedAliases = visitedSymbols.takeVector();
1120 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1124 llvm::BumpPtrAllocator usedAliasAllocator;
1125 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1127 llvm::StringMap<unsigned> nameCounts;
1128 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1129 if (!aliasInfo.alias)
1131 StringRef alias = *aliasInfo.alias;
1132 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1133 symbolToAlias.insert(
1134 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1135 aliasInfo.canBeDeferred)});
1139void AliasInitializer::initialize(
1141 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1145 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1146 aliasPrinter.printCustomOrGenericOp(op);
1149 initializeAliases(aliases, attrTypeToAlias);
1152template <
typename T,
typename... PrintArgs>
1153std::pair<size_t, size_t> AliasInitializer::visitImpl(
1154 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1155 bool canBeDeferred, PrintArgs &&...
printArgs) {
1156 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1157 size_t aliasIndex = std::distance(aliases.begin(), it);
1161 markAliasNonDeferrable(aliasIndex);
1162 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1166 generateAlias(value, it->second, canBeDeferred);
1167 it->second.isType = std::is_base_of_v<Type, T>;
1168 it->second.canBeDeferred = canBeDeferred;
1172 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1173 size_t maxAliasDepth =
1174 printer.printAndVisitNestedAliases(value,
printArgs...);
1177 it = std::next(aliases.begin(), aliasIndex);
1180 it->second.childIndices = std::move(childAliases);
1182 it->second.aliasDepth = maxAliasDepth + 1;
1185 return {(size_t)it->second.aliasDepth, aliasIndex};
1188void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1189 auto *it = std::next(aliases.begin(), aliasIndex);
1193 if (!it->second.canBeDeferred)
1196 it->second.canBeDeferred =
false;
1199 for (
size_t childIndex : it->second.childIndices)
1200 markAliasNonDeferrable(childIndex);
1203template <
typename T>
1204void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1205 bool canBeDeferred) {
1209 OpAsmDialectInterface::AliasResult::NoAlias;
1210 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1211 OpAsmAttrInterface, OpAsmTypeInterface>;
1212 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1213 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1214 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1215 nameBuffer = std::move(aliasBuffer);
1216 assert(!nameBuffer.empty() &&
"expected valid alias name");
1220 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1221 for (
const auto &interface : interfaces) {
1223 interface.getAlias(symbol, aliasOS);
1224 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1226 nameBuffer = std::move(aliasBuffer);
1227 assert(!nameBuffer.empty() &&
"expected valid alias name");
1228 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1233 if (nameBuffer.empty())
1239 name = name.copy(aliasAllocator);
1240 alias = InProgressAliasInfo(name);
1253 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1254 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1258 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1262 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1266 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1267 printAliases(p, newLine,
false);
1271 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1272 printAliases(p, newLine,
true);
1278 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1282 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1285 llvm::BumpPtrAllocator aliasAllocator;
1289void AliasState::initialize(
1292 AliasInitializer initializer(interfaces, aliasAllocator);
1293 initializer.initialize(op, printerFlags, attrTypeToAlias);
1298 if (it == attrTypeToAlias.end())
1300 it->second.print(os);
1306 if (it == attrTypeToAlias.end())
1308 if (!it->second.isPrinted)
1311 it->second.print(os);
1317 auto filterFn = [=](
const auto &aliasIt) {
1318 return aliasIt.second.canBeDeferred() == isDeferred;
1320 for (
auto &[opaqueSymbol, alias] :
1321 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1325 if (alias.isTypeAlias()) {
1328 alias.isPrinted =
true;
1358 enum :
unsigned { NameSentinel = ~0U };
1360 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1361 SSANameState() =
default;
1366 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1369 void printOperationID(Operation *op, raw_ostream &stream)
const;
1373 ArrayRef<int> getOpResultGroups(Operation *op);
1376 BlockInfo getBlockInfo(
Block *block);
1381 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1385 void numberValuesInRegion(Region ®ion);
1386 void numberValuesInBlock(
Block &block);
1387 void numberValuesInOp(Operation &op);
1393 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1394 std::optional<int> &lookupResultNo)
const;
1397 void setValueName(Value value, StringRef name);
1401 StringRef uniqueValueName(StringRef name);
1424 llvm::ScopedHashTable<StringRef, char> usedNames;
1425 llvm::BumpPtrAllocator usedNameAllocator;
1428 unsigned nextValueID = 0;
1430 unsigned nextArgumentID = 0;
1432 unsigned nextConflictID = 0;
1436 OpPrintingFlags printerFlags;
1441 : printerFlags(printerFlags) {
1442 llvm::SaveAndRestore valueIDSaver(nextValueID);
1443 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1444 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1449 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1450 using NamingContext =
1451 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1454 llvm::BumpPtrAllocator allocator;
1457 auto *topLevelNamesScope =
1458 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1462 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1463 nextConflictID, topLevelNamesScope));
1465 numberValuesInOp(*op);
1467 while (!nameContext.empty()) {
1469 UsedNamesScopeTy *parentScope;
1473 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1474 nameContext.pop_back_val();
1476 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1477 parentScope) = nameContext.pop_back_val();
1481 while (usedNames.getCurScope() != parentScope) {
1482 usedNames.getCurScope()->~UsedNamesScopeTy();
1483 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1484 "top level parentScope must be a nullptr");
1488 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1489 UsedNamesScopeTy(usedNames);
1491 numberValuesInRegion(*region);
1495 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1496 nextArgumentID, nextConflictID,
1501 while (usedNames.getCurScope() !=
nullptr)
1502 usedNames.getCurScope()->~UsedNamesScopeTy();
1505void SSANameState::printValueID(
Value value,
bool printResultNo,
1508 stream <<
"<<NULL VALUE>>";
1512 std::optional<int> resultNo;
1513 auto lookupValue = value;
1517 if (OpResult
result = dyn_cast<OpResult>(value))
1518 getResultIDAndNumber(
result, lookupValue, resultNo);
1520 auto it = valueIDs.find(lookupValue);
1521 if (it == valueIDs.end()) {
1522 stream <<
"<<UNKNOWN SSA VALUE>>";
1527 if (it->second != NameSentinel) {
1528 stream << it->second;
1530 auto nameIt = valueNames.find(lookupValue);
1531 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1532 stream << nameIt->second;
1535 if (resultNo && printResultNo)
1536 stream <<
'#' << *resultNo;
1539void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1540 auto it = operationIDs.find(op);
1541 if (it == operationIDs.end()) {
1542 stream <<
"<<UNKNOWN OPERATION>>";
1544 stream <<
'%' << it->second;
1548ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1549 auto it = opResultGroups.find(op);
1550 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1553BlockInfo SSANameState::getBlockInfo(
Block *block) {
1554 auto it = blockNames.find(block);
1555 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1556 return it != blockNames.end() ? it->second : invalidBlock;
1559void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1560 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1562 "incorrect number of names passed in");
1564 "only KnownIsolatedFromAbove ops can shadow names");
1566 SmallVector<char, 16> nameStr;
1567 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1568 auto nameToUse = namesToUse[i];
1569 if (nameToUse ==
nullptr)
1574 llvm::raw_svector_ostream nameStream(nameStr);
1575 printValueID(nameToUse,
true, nameStream);
1578 assert(valueIDs[nameToReplace] == NameSentinel);
1581 auto name = StringRef(nameStream.str()).drop_front();
1584 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1590StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1592 return maybeNameLoc.getName();
1597void SSANameState::numberValuesInRegion(Region ®ion) {
1599 bool opAsmOpInterfaceUsed =
false;
1600 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1601 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1602 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1603 "arg not defined in current region");
1604 opAsmOpInterfaceUsed =
true;
1606 name = maybeGetValueNameFromLoc(arg, name);
1607 setValueName(arg, name);
1612 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1613 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1615 if (!opAsmOpInterfaceUsed) {
1617 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1618 interface.getAsmName(
1619 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1627 unsigned nextBlockID = 0;
1628 for (
auto &block : region) {
1631 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1632 if (blockInfoIt.second) {
1636 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1637 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1639 blockInfoIt.first->second.ordering = nextBlockID++;
1641 numberValuesInBlock(block);
1645void SSANameState::numberValuesInBlock(
Block &block) {
1649 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1650 llvm::raw_svector_ostream specialName(specialNameBuffer);
1652 if (valueIDs.count(arg))
1655 specialNameBuffer.resize(strlen(
"arg"));
1656 specialName << nextArgumentID++;
1658 StringRef specialNameStr = specialName.str();
1660 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1661 setValueName(arg, specialNameStr);
1665 for (
auto &op : block)
1666 numberValuesInOp(op);
1669void SSANameState::numberValuesInOp(Operation &op) {
1671 SmallVector<int, 2> resultGroups(1, 0);
1673 bool opAsmOpInterfaceUsed =
false;
1674 auto setResultNameFn = [&](Value
result, StringRef name) {
1675 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1676 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1677 opAsmOpInterfaceUsed =
true;
1679 name = maybeGetValueNameFromLoc(
result, name);
1680 setValueName(
result, name);
1683 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1684 resultGroups.push_back(resultNo);
1687 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1689 "getAsmBlockArgumentNames callback invoked on a block not directly "
1690 "nested under the current operation");
1691 assert(!blockNames.count(block) &&
"block numbered multiple times");
1692 SmallString<16> tmpBuffer{
"^"};
1694 if (name.data() != tmpBuffer.data()) {
1695 tmpBuffer.append(name);
1696 name = tmpBuffer.str();
1698 name = name.copy(usedNameAllocator);
1699 blockNames[block] = {-1, name};
1703 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1704 asmInterface.getAsmBlockNames(setBlockNameFn);
1705 asmInterface.getAsmResultNames(setResultNameFn);
1707 if (!opAsmOpInterfaceUsed) {
1710 bool allHaveOpAsmTypeInterface =
1712 return isa<OpAsmTypeInterface>(type);
1714 if (allHaveOpAsmTypeInterface) {
1716 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1717 interface.getAsmName(
1718 [&](StringRef name) { setResultNameFn(
result, name); });
1725 if (numResults == 0) {
1728 if (operationIDs.try_emplace(&op, nextValueID).second)
1737 setValueName(resultBegin, nameLoc.getName());
1742 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1746 if (resultGroups.size() != 1) {
1747 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1748 opResultGroups.try_emplace(&op, std::move(resultGroups));
1752void SSANameState::getResultIDAndNumber(
1753 OpResult
result, Value &lookupValue,
1754 std::optional<int> &lookupResultNo)
const {
1755 Operation *owner =
result.getOwner();
1758 int resultNo =
result.getResultNumber();
1762 auto resultGroupIt = opResultGroups.find(owner);
1763 if (resultGroupIt == opResultGroups.end()) {
1765 lookupResultNo = resultNo;
1771 ArrayRef<int> resultGroups = resultGroupIt->second;
1772 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1773 int groupResultNo = 0, groupSize = 0;
1776 if (it == resultGroups.end()) {
1777 groupResultNo = resultGroups.back();
1778 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1781 groupResultNo = *std::prev(it);
1782 groupSize = *it - groupResultNo;
1787 lookupResultNo = resultNo - groupResultNo;
1788 lookupValue = owner->
getResult(groupResultNo);
1791void SSANameState::setValueName(Value value, StringRef name) {
1794 valueIDs[value] = nextValueID++;
1798 valueIDs[value] = NameSentinel;
1799 valueNames[value] = uniqueValueName(name);
1802StringRef SSANameState::uniqueValueName(StringRef name) {
1803 SmallString<16> tmpBuffer;
1807 if (!usedNames.count(name)) {
1808 name = name.copy(usedNameAllocator);
1813 SmallString<64> probeName(name);
1814 probeName.push_back(
'_');
1816 probeName += llvm::utostr(nextConflictID++);
1817 if (!usedNames.count(probeName)) {
1818 name = probeName.str().copy(usedNameAllocator);
1821 probeName.resize(name.size() + 1);
1825 usedNames.insert(name,
char());
1835class DistinctState {
1838 uint64_t getId(DistinctAttr distinctAttr);
1841 uint64_t distinctCounter = 0;
1846uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1848 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1851 return it->getSecond();
1872 llvm_unreachable(
"unknown AsmResourceEntryKind");
1876 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1878 collection = std::make_unique<ResourceCollection>(key);
1882std::vector<std::unique_ptr<AsmResourcePrinter>>
1884 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1885 for (
auto &it : keyToResources) {
1886 ResourceCollection *collection = it.second.get();
1888 return collection->buildResources(op, builder);
1890 printers.emplace_back(
1896LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1900 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1903 resources.emplace_back(entry.
getKey(), std::move(*blob));
1910 resources.emplace_back(entry.
getKey(), *value);
1913 case AsmResourceEntryKind::String: {
1917 resources.emplace_back(entry.
getKey(), std::move(*str));
1924void FallbackAsmResourceMap::ResourceCollection::buildResources(
1925 Operation *op, AsmResourceBuilder &builder)
const {
1926 for (
const auto &entry : resources) {
1927 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1929 else if (
const auto *value = std::get_if<bool>(&entry.value))
1931 else if (
const auto *value = std::get_if<std::string>(&entry.value))
1934 llvm_unreachable(
"unknown AsmResourceEntryKind");
1948 : interfaces(op->
getContext()), nameState(op, printerFlags),
1949 printerFlags(printerFlags), locationMap(locationMap) {}
1952 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
1956 aliasState.initialize(op, printerFlags, interfaces);
1976 return llvm::make_pointee_range(externalResourcePrinters);
1986 (*locationMap)[op] = std::make_pair(line, col);
1992 return dialectResources;
1996 return success(cyclicPrintingStack.insert(opaquePointer));
2012 AliasState aliasState;
2015 SSANameState nameState;
2018 DistinctState distinctState;
2034template <
typename Range>
2038 [&stream](
const auto &dimSize) {
2039 if (ShapedType::isDynamic(dimSize))
2057 return printerFlags;
2061 auto parentThreadId = llvm::get_threadid();
2063 if (parentThreadId == llvm::get_threadid()) {
2065 diag.print(llvm::dbgs());
2066 llvm::dbgs() <<
"\n";
2074 <<
"' failed to verify and will be printed in generic form";
2078 return printerFlags;
2097 return impl->getPrinterFlags();
2101 std::unique_ptr<AsmResourcePrinter> printer) {
2102 impl->externalResourcePrinters.emplace_back(std::move(printer));
2107 return impl->getDialectResources();
2129 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2133 .Case<OpaqueLoc>([&](OpaqueLoc loc) {
2136 .Case<UnknownLoc>([&](UnknownLoc loc) {
2144 os << loc.getFilename().getValue();
2147 if (loc.getEndColumn() == loc.getStartColumn() &&
2148 loc.getStartLine() == loc.getEndLine()) {
2149 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2152 if (loc.getStartLine() == loc.getEndLine()) {
2153 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2154 <<
" to :" << loc.getEndColumn();
2157 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2158 << loc.getEndLine() <<
':' << loc.getEndColumn();
2160 .Case<NameLoc>([&](NameLoc loc) {
2164 auto childLoc = loc.getChildLoc();
2165 if (!llvm::isa<UnknownLoc>(childLoc)) {
2171 .Case<CallSiteLoc>([&](CallSiteLoc loc) {
2178 if (llvm::isa<NameLoc>(callee)) {
2179 if (llvm::isa<FileLineColLoc>(caller)) {
2194 .Case<FusedLoc>([&](
FusedLoc loc) {
2197 if (
Attribute metadata = loc.getMetadata()) {
2204 printLocationInternal(loc, pretty);
2218 bool *printedHex =
nullptr) {
2223 bool isInf = apValue.isInfinity();
2224 bool isNaN = apValue.isNaN();
2225 if (!isInf && !isNaN) {
2227 apValue.toString(strValue, 6, 0,
2233 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2234 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2235 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2236 "[-+]?[0-9] regex does not match!");
2240 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2248 apValue.toString(strValue);
2251 if (strValue.str().contains(
'.')) {
2262 APInt apInt = apValue.bitcastToAPInt();
2263 apInt.toString(str, 16,
false,
2283 if (symName.empty() || !isalpha(symName.front()))
2288 symName = symName.drop_while(
2289 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2290 if (symName.empty())
2295 return symName.front() ==
'<' && symName.back() ==
'>';
2300 StringRef dialectName, StringRef symString) {
2301 os << symPrefix << dialectName;
2306 os <<
'.' << symString;
2310 os <<
'<' << symString <<
'>';
2319 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2321 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2322 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2337 printEscapedString(keyword, os);
2345 if (symbolRef.empty()) {
2346 os <<
"@<<INVALID EMPTY SYMBOL>>";
2359 os << R
"(dense_resource<__elided__>)";
2370 return state.getAliasState().getAlias(attr,
os);
2374 return state.getAliasState().getAlias(type,
os);
2380 os <<
"<<NULL ATTRIBUTE>>";
2391 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2393 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2395 opaqueAttr.getAttrData());
2396 }
else if (llvm::isa<UnitAttr>(attr)) {
2399 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2400 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2406 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2412 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2413 Type intType = intAttr.getType();
2415 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2426 intAttr.getValue().print(
os, !isUnsigned);
2432 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2433 bool printedHex =
false;
2441 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2444 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2447 printAttribute(attr, AttrTypeElision::May);
2451 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2452 os <<
"affine_map<";
2453 affineMapAttr.getValue().print(
os);
2459 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2460 os <<
"affine_set<";
2461 integerSetAttr.getValue().print(
os);
2467 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2470 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2477 }
else if (
auto intOrFpEltAttr =
2478 llvm::dyn_cast<DenseIntOrFPElementsAttr>(attr)) {
2479 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2487 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2488 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2496 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2497 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2498 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2503 if (
indices.getNumElements() != 0) {
2510 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2511 stridedLayoutAttr.print(
os);
2512 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2514 printType(denseArrayAttr.getElementType());
2515 if (!denseArrayAttr.empty()) {
2521 }
else if (
auto resourceAttr =
2522 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2523 os <<
"dense_resource<";
2526 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2529 llvm::report_fatal_error(
"Unknown builtin attribute");
2533 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2534 Type attrType = typedAttr.getType();
2535 if (!llvm::isa<NoneType>(attrType)) {
2547 os << (value.getBoolValue() ?
"true" :
"false");
2557 return printEltFn(0);
2560 auto numElements = type.getNumElements();
2561 if (numElements == 0)
2569 int64_t rank = type.getRank();
2572 unsigned openBrackets = 0;
2574 auto shape = type.getShape();
2575 auto bumpCounter = [&] {
2577 ++counter[rank - 1];
2579 for (
unsigned i = rank - 1; i > 0; --i)
2580 if (counter[i] >=
shape[i]) {
2589 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2592 while (openBrackets++ < rank)
2594 openBrackets = rank;
2598 while (openBrackets-- > 0)
2604 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2613 auto type = attr.getType();
2614 auto elementType = type.getElementType();
2617 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2619 if (llvm::endianness::native == llvm::endianness::big) {
2624 DenseIntOrFPElementsAttr::convertEndianOfArrayRefForBEmachine(
2625 rawData, convRawData, type);
2634 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2635 Type complexElementType = complexTy.getElementType();
2639 if (llvm::isa<IntegerType>(complexElementType)) {
2640 auto valueIt = attr.value_begin<std::complex<APInt>>();
2642 auto complexValue = *(valueIt + index);
2644 printDenseIntElement(complexValue.real(), os, complexElementType);
2646 printDenseIntElement(complexValue.imag(), os, complexElementType);
2650 auto valueIt = attr.value_begin<std::complex<APFloat>>();
2652 auto complexValue = *(valueIt + index);
2654 printFloatValue(complexValue.real(), os);
2656 printFloatValue(complexValue.imag(), os);
2660 }
else if (elementType.isIntOrIndex()) {
2661 auto valueIt = attr.value_begin<APInt>();
2663 printDenseIntElement(*(valueIt + index), os, elementType);
2666 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2667 auto valueIt = attr.value_begin<APFloat>();
2669 printFloatValue(*(valueIt + index), os);
2675 DenseStringElementsAttr attr) {
2682 Type type = attr.getElementType();
2684 unsigned byteSize = bitwidth / 8;
2687 auto printElementAt = [&](
unsigned i) {
2688 APInt value(bitwidth, 0);
2690 llvm::LoadIntFromMemory(
2691 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2698 APFloat fltVal(llvm::cast<FloatType>(type).getFloatSemantics(), value);
2702 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2708 os <<
"<<NULL TYPE>>";
2720 .Case<OpaqueType>([&](OpaqueType opaqueTy) {
2722 opaqueTy.getTypeData());
2724 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2725 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2726 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2727 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2728 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2729 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2730 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2731 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2732 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2733 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2734 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2735 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2736 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2737 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2738 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2739 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2740 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2741 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2742 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2743 .Case<IntegerType>([&](IntegerType integerTy) {
2744 if (integerTy.isSigned())
2746 else if (integerTy.isUnsigned())
2748 os <<
'i' << integerTy.getWidth();
2750 .Case<FunctionType>([&](FunctionType funcTy) {
2755 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2763 .Case<VectorType>([&](VectorType vectorTy) {
2764 auto scalableDims = vectorTy.getScalableDims();
2766 auto vShape = vectorTy.getShape();
2767 unsigned lastDim = vShape.size();
2768 unsigned dimIdx = 0;
2769 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2770 if (!scalableDims.empty() && scalableDims[dimIdx])
2772 os << vShape[dimIdx];
2773 if (!scalableDims.empty() && scalableDims[dimIdx])
2780 .Case<RankedTensorType>([&](RankedTensorType tensorTy) {
2783 if (!tensorTy.getShape().empty())
2787 if (tensorTy.getEncoding()) {
2793 .Case<UnrankedTensorType>([&](UnrankedTensorType tensorTy) {
2798 .Case<MemRefType>([&](MemRefType memrefTy) {
2801 if (!memrefTy.getShape().empty())
2804 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2805 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2810 if (memrefTy.getMemorySpace()) {
2820 if (memrefTy.getMemorySpace()) {
2826 .Case<ComplexType>([&](ComplexType complexTy) {
2831 .Case<TupleType>([&](TupleType tupleTy) {
2834 [&](
Type type) { printType(type); });
2837 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2838 .Case<GraphType>([&](GraphType graphTy) {
2843 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2862 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2865 os <<
" attributes";
2875 if (elidedAttrs.empty())
2876 return printFilteredAttributesFn(attrs);
2879 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2881 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2882 return !elidedAttrsSet.contains(attr.
getName().strref());
2884 if (!filteredAttrs.empty())
2885 printFilteredAttributesFn(filteredAttrs);
2892 if (llvm::isa<UnitAttr>(attr.
getValue()))
2903 std::string attrName;
2905 llvm::raw_string_ostream attrNameStr(attrName);
2908 dialect.printAttribute(attr, printer);
2917 std::string typeName;
2919 llvm::raw_string_ostream typeNameStr(typeName);
2922 dialect.printType(type, printer);
2929 llvm::printEscapedString(str,
os);
2934 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
2941 return state.pushCyclicPrinting(opaquePointer);
2957 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
2958 return impl->getStream();
2963 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
2968 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
2969 impl->printType(type);
2973 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
2974 impl->printAttribute(attr);
2978 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
2979 return impl->printAlias(attr);
2983 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
2984 return impl->printAlias(type);
2989 "expected AsmPrinter::printAttributeWithoutType to be overriden");
2994 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
2995 impl->printNamedAttribute(attr);
2999 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3004 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3006 printEscapedString(keyword,
getStream());
3011 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3016 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3017 impl->printResourceHandle(resource);
3025 return impl->pushCyclicPrinting(opaquePointer);
3042 const char *binopSpelling =
nullptr;
3045 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3047 printValueName(pos,
true);
3053 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3055 printValueName(pos,
false);
3061 os << cast<AffineConstantExpr>(expr).getValue();
3064 binopSpelling =
" + ";
3067 binopSpelling =
" * ";
3070 binopSpelling =
" floordiv ";
3073 binopSpelling =
" ceildiv ";
3076 binopSpelling =
" mod ";
3080 auto binOp = cast<AffineBinaryOpExpr>(expr);
3090 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3092 rhsConst.getValue() == -1) {
3102 os << binopSpelling;
3116 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3119 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3120 if (rrhs.getValue() == -1) {
3137 if (rrhs.getValue() < -1) {
3143 os <<
" * " << -rrhs.getValue();
3153 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3154 if (rhsConst.getValue() < 0) {
3156 os <<
" - " << -rhsConst.getValue();
3174 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3180 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3181 os <<
'd' << i <<
", ";
3190 os <<
's' << i <<
", ";
3199 [&](
AffineExpr expr) { printAffineExpr(expr); });
3206 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3207 os <<
'd' << i - 1 <<
", ";
3216 os <<
's' << i <<
", ";
3225 for (
int i = 1; i < numConstraints; ++i) {
3229 if (numConstraints >= 1)
3231 set.
isEq(numConstraints - 1));
3250 void printTopLevelOperation(
Operation *op);
3254 void printFullOpWithIndentAndLoc(
Operation *op);
3260 void printCustomOrGenericOp(
Operation *op)
override;
3262 void printGenericOp(
Operation *op,
bool printOpName)
override;
3265 void printBlockName(
Block *block);
3270 void print(
Block *block,
bool printBlockArgs =
true,
3271 bool printBlockTerminator =
true);
3274 void printValueID(
Value value,
bool printResultNo =
true,
3287 void printOptionalLocationSpecifier(
Location loc)
override {
3288 printTrailingLocation(loc);
3295 os.indent(currentIndent);
3299 void increaseIndent()
override { currentIndent += indentWidth; }
3302 void decreaseIndent()
override { currentIndent -= indentWidth; }
3309 void printRegionArgument(BlockArgument arg,
3310 ArrayRef<NamedAttribute> argAttrs = {},
3311 bool omitType =
false)
override;
3314 void printOperand(Value value)
override { printValueID(value); }
3315 void printOperand(Value value, raw_ostream &os)
override {
3316 printValueID(value,
true, &os);
3320 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3321 ArrayRef<StringRef> elidedAttrs = {})
override {
3322 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3324 void printOptionalAttrDictWithKeyword(
3325 ArrayRef<NamedAttribute> attrs,
3326 ArrayRef<StringRef> elidedAttrs = {})
override {
3327 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3332 void printSuccessor(
Block *successor)
override;
3336 void printSuccessorAndUseList(
Block *successor,
3340 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3341 bool printBlockTerminators,
bool printEmptyBlock)
override;
3347 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3353 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3358 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3362 void printUsersComment(Operation *op);
3365 void printUsersComment(BlockArgument arg);
3368 void printValueUsers(Value value);
3372 void printUserIDs(Operation *user,
bool prefixComma =
false);
3377 class ResourceBuilder :
public AsmResourceBuilder {
3380 using PrintFn =
function_ref<void(StringRef, ValueFn)>;
3382 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3383 ~ResourceBuilder()
override =
default;
3385 void buildBool(StringRef key,
bool data)
final {
3386 printFn(key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); });
3389 void buildString(StringRef key, StringRef data)
final {
3390 printFn(key, [&](raw_ostream &os) {
3392 llvm::printEscapedString(data, os);
3397 void buildBlob(StringRef key, ArrayRef<char> data,
3398 uint32_t dataAlignment)
final {
3399 printFn(key, [&](raw_ostream &os) {
3401 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3403 << llvm::toHex(StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3404 sizeof(dataAlignment)))
3405 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3414 void printFileMetadataDictionary(Operation *op);
3420 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3428 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3431 const static unsigned indentWidth = 2;
3434 unsigned currentIndent = 0;
3438void OperationPrinter::printTopLevelOperation(Operation *op) {
3440 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3443 printFullOpWithIndentAndLoc(op);
3450 printFileMetadataDictionary(op);
3453void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3454 bool sawMetadataEntry =
false;
3455 auto checkAddMetadataDict = [&] {
3456 if (!std::exchange(sawMetadataEntry,
true))
3457 os << newLine <<
"{-#" << newLine;
3461 printResourceFileMetadata(checkAddMetadataDict, op);
3464 if (sawMetadataEntry)
3465 os << newLine <<
"#-}" << newLine;
3468void OperationPrinter::printResourceFileMetadata(
3469 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3471 bool hadResource =
false;
3472 bool needResourceComma =
false;
3473 bool needEntryComma =
false;
3474 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3475 auto &&...providerArgs) {
3476 bool hadEntry =
false;
3477 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn) {
3478 checkAddMetadataDict();
3480 std::string resourceStr;
3481 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3482 std::optional<uint64_t> charLimit =
3484 if (charLimit.has_value()) {
3486 if (charLimit.value() == 0)
3489 llvm::raw_string_ostream ss(resourceStr);
3493 if (resourceStr.size() > charLimit.value())
3497 valueFn = printResourceStr;
3501 if (!std::exchange(hadResource,
true)) {
3502 if (needResourceComma)
3503 os <<
"," << newLine;
3504 os <<
" " << dictName <<
"_resources: {" << newLine;
3507 if (!std::exchange(hadEntry,
true)) {
3509 os <<
"," << newLine;
3510 os <<
" " << name <<
": {" << newLine;
3512 os <<
"," << newLine;
3520 ResourceBuilder entryBuilder(printFn);
3521 provider.buildResources(op, providerArgs..., entryBuilder);
3523 needEntryComma |= hadEntry;
3525 os << newLine <<
" }";
3532 StringRef name = interface.getDialect()->getNamespace();
3533 auto it = dialectResources.find(interface.getDialect());
3534 if (it != dialectResources.end())
3535 processProvider(
"dialect", name, interface, it->second);
3537 processProvider(
"dialect", name, interface,
3541 os << newLine <<
" }";
3545 needEntryComma =
false;
3546 needResourceComma = hadResource;
3547 hadResource =
false;
3549 processProvider(
"external", printer.getName(), printer);
3551 os << newLine <<
" }";
3559void OperationPrinter::printRegionArgument(BlockArgument arg,
3560 ArrayRef<NamedAttribute> argAttrs,
3567 printOptionalAttrDict(argAttrs);
3569 printTrailingLocation(arg.
getLoc(),
false);
3572void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3576 os.indent(currentIndent);
3578 printTrailingLocation(op->
getLoc());
3580 printUsersComment(op);
3583void OperationPrinter::printFullOp(Operation *op) {
3585 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3586 printValueID(op->
getResult(resultNo),
false);
3587 if (resultCount > 1)
3588 os <<
':' << resultCount;
3592 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3593 if (!resultGroups.empty()) {
3596 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3597 printResultGroup(resultGroups[i],
3598 resultGroups[i + 1] - resultGroups[i]);
3601 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3604 printResultGroup(0, numResults);
3610 printCustomOrGenericOp(op);
3613void OperationPrinter::printUsersComment(Operation *op) {
3617 printOperationID(op);
3618 }
else if (numResults && op->
use_empty()) {
3620 }
else if (numResults && !op->
use_empty()) {
3623 unsigned usedInNResults = 0;
3624 unsigned usedInNOperations = 0;
3625 SmallPtrSet<Operation *, 1> userSet;
3626 for (Operation *user : op->
getUsers()) {
3627 if (userSet.insert(user).second) {
3628 ++usedInNOperations;
3629 usedInNResults += user->getNumResults();
3634 bool exactlyOneUniqueUse =
3635 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3636 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3637 bool shouldPrintBrackets = numResults > 1;
3638 auto printOpResult = [&](OpResult opResult) {
3639 if (shouldPrintBrackets)
3641 printValueUsers(opResult);
3642 if (shouldPrintBrackets)
3646 interleaveComma(op->
getResults(), printOpResult);
3650void OperationPrinter::printUsersComment(BlockArgument arg) {
3656 os <<
" is used by ";
3657 printValueUsers(arg);
3662void OperationPrinter::printValueUsers(Value value) {
3668 SmallPtrSet<Operation *, 1> userSet;
3670 if (userSet.insert(user).second)
3671 printUserIDs(user, index);
3675void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3680 printOperationID(user);
3683 [
this](Value
result) { printValueID(result); });
3687void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3693 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3698 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3703 if (name.count(
'.') == 1)
3704 name.consume_front((defaultDialectStack.back() +
".").str());
3708 opPrinter(op, *
this);
3715 printGenericOp(op,
true);
3718void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3722 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3729 [&](
Block *successor) { printBlockName(successor); });
3743 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3744 printRegion(region, true,
3759void OperationPrinter::printBlockName(
Block *block) {
3763void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3764 bool printBlockTerminator) {
3766 if (printBlockArgs) {
3767 os.indent(currentIndent);
3768 printBlockName(block);
3773 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3776 printType(arg.getType());
3778 printTrailingLocation(arg.getLoc(), false);
3786 os <<
" // block is not in a region!";
3789 os <<
" // no predecessors";
3792 printBlockName(pred);
3796 SmallVector<BlockInfo, 4> predIDs;
3799 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3800 return lhs.ordering <
rhs.ordering;
3803 os <<
" // " << predIDs.size() <<
" preds: ";
3805 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3810 currentIndent += indentWidth;
3814 os.indent(currentIndent);
3815 printUsersComment(arg);
3819 bool hasTerminator =
3821 auto range = llvm::make_range(
3823 std::prev(block->
end(),
3824 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3825 for (
auto &op : range) {
3826 printFullOpWithIndentAndLoc(&op);
3829 currentIndent -= indentWidth;
3832void OperationPrinter::printValueID(Value value,
bool printResultNo,
3833 raw_ostream *streamOverride)
const {
3835 streamOverride ? *streamOverride : os);
3838void OperationPrinter::printOperationID(Operation *op,
3839 raw_ostream *streamOverride)
const {
3840 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3844void OperationPrinter::printSuccessor(
Block *successor) {
3845 printBlockName(successor);
3848void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3850 printBlockName(successor);
3851 if (succOperands.empty())
3855 interleaveComma(succOperands,
3856 [
this](Value operand) { printValueID(operand); });
3858 interleaveComma(succOperands,
3863void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
3864 bool printBlockTerminators,
3865 bool printEmptyBlock) {
3870 os <<
"{" << newLine;
3871 if (!region.
empty()) {
3872 auto restoreDefaultDialect =
3873 llvm::make_scope_exit([&]() { defaultDialectStack.pop_back(); });
3874 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
3875 defaultDialectStack.push_back(iface.getDefaultDialect());
3877 defaultDialectStack.push_back(
"");
3879 auto *entryBlock = ®ion.
front();
3883 bool shouldAlwaysPrintBlockHeader =
3884 (printEmptyBlock && entryBlock->empty()) ||
3885 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
3886 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
3887 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
3890 os.indent(currentIndent) <<
"}";
3893void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3896 os <<
"<<NULL AFFINE MAP>>";
3899 AffineMap map = mapAttr.getValue();
3901 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3902 unsigned index = isSymbol ? numDims + pos : pos;
3903 assert(index < operands.size());
3906 printValueID(operands[index]);
3911 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
3912 printAffineExpr(expr, printValueName);
3916void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
3919 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3921 return printValueID(dimOperands[pos]);
3923 printValueID(symOperands[pos]);
3926 printAffineExpr(expr, printValueName);
3935 os <<
"<<NULL ATTRIBUTE>>";
3940 print(os, state, elideType);
3946 : AttrTypeElision::Never);
3950 print(llvm::errs());
3951 llvm::errs() <<
"\n";
3956 os <<
"<<NULL ATTRIBUTE>>";
3965 uint64_t posPrior = os.tell();
3967 dialect.printAttribute(*
this, printer);
3968 if (posPrior != os.tell())
3977 os <<
"<<NULL ATTRIBUTE>>";
3987 os <<
"<<NULL TYPE>>";
3999 print(llvm::errs());
4000 llvm::errs() <<
"\n";
4004 print(llvm::errs());
4005 llvm::errs() <<
"\n";
4009 print(llvm::errs());
4010 llvm::errs() <<
"\n";
4015 os <<
"<<NULL AFFINE EXPR>>";
4023 print(llvm::errs());
4024 llvm::errs() <<
"\n";
4029 os <<
"<<NULL AFFINE MAP>>";
4044 os <<
"<<NULL VALUE>>";
4049 return op->
print(os, flags);
4052 os <<
"<block argument> of type '" << arg.
getType()
4057 os <<
"<<NULL VALUE>>";
4062 return op->
print(os, state);
4066 os <<
"<block argument> of type '" << arg.
getType()
4071 print(llvm::errs());
4072 llvm::errs() <<
"\n";
4103 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4106 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4108 os <<
"<<UNKNOWN SSA VALUE>>";
4124 OperationPrinter printer(os, state.
getImpl());
4127 printer.printTopLevelOperation(
this);
4129 printer.printFullOpWithIndentAndLoc(
this);
4135 llvm::errs() <<
"\n";
4140 llvm::errs() <<
"\n";
4146 os <<
"<<UNLINKED BLOCK>>\n";
4157 OperationPrinter(os, state.
getImpl()).print(
this);
4166 os <<
"<<UNLINKED BLOCK>>\n";
4173 OperationPrinter printer(os, state.
getImpl());
4174 printer.printBlockName(
this);
4189 if (dimensions.empty())
4192 if (dimensions.empty())
4202 <<
"Failed parsing dimension list.";
4213 <<
"Failed parsing dimension list.";
4215 if (shapeArr.empty()) {
4217 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4218 "must be denoted by \"[]\".";
static void printSymbolReference(StringRef symbolRef, raw_ostream &os)
Print the given string as a symbol reference.
static void printFloatValue(const APFloat &apValue, raw_ostream &os, bool *printedHex=nullptr)
Print a floating point value in a way that the parser will be able to round-trip losslessly.
static StringRef sanitizeIdentifier(StringRef name, SmallString< 16 > &buffer, StringRef allowedPunctChars="$._-")
Sanitize the given name such that it can be used as a valid identifier.
static void printElidedElementsAttr(raw_ostream &os)
static bool isBareIdentifier(StringRef name)
Returns true if the given string can be represented as a bare identifier.
static void printDenseElementsAttrImpl(bool isSplat, ShapedType type, raw_ostream &os, function_ref< void(unsigned)> printEltFn)
static void printKeywordOrString(StringRef keyword, raw_ostream &os)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
static bool isDialectSymbolSimpleEnoughForPrettyForm(StringRef symName)
Returns true if the given dialect symbol data is simple enough to print in the pretty form.
static void printDialectSymbol(raw_ostream &os, StringRef symPrefix, StringRef dialectName, StringRef symString)
Print the given dialect symbol to the stream.
static OpPrintingFlags verifyOpAndAdjustFlags(Operation *op, OpPrintingFlags printerFlags)
Verifies the operation and switches to generic op printing if verification fails.
static void printDenseIntElement(const APInt &value, raw_ostream &os, Type type)
Print the integer element of a DenseElementsAttr.
MLIR_CRUNNERUTILS_EXPORT void printString(char const *s)
MLIR_CRUNNERUTILS_EXPORT void printNewline()
static llvm::ManagedStatic< DebugCounterOptions > clOptions
static void visit(Operation *op, DenseSet< Operation * > &visited)
Visits all the pdl.operand(s), pdl.result(s), and pdl.operation(s) connected to the given operation.
LogicalResult initialize(unsigned origNumLoops, ArrayRef< ReassociationIndices > foldedIterationDims)
static Operation * findParent(Operation *op, bool shouldUseLocalScope)
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static std::string diag(const llvm::Value &value)
false
Parses a map_entries map type from a string format back into its numeric value.
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static void printRegion(llvm::raw_ostream &os, Region *region, OpPrintingFlags &flags)
Base type for affine expression.
AffineExprKind getKind() const
Return the classification for this type.
void print(raw_ostream &os) const
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
unsigned getNumSymbols() const
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
void print(raw_ostream &os) const
This class represents an opaque handle to a dialect resource entry.
Dialect * getDialect() const
Return the dialect that owns the resource.
This class represents a single parsed resource entry.
virtual InFlightDiagnostic emitError() const =0
Emit an error at the location of this entry.
virtual AsmResourceEntryKind getKind() const =0
Return the kind of this value.
virtual FailureOr< AsmResourceBlob > parseAsBlob(BlobAllocatorFn allocator) const =0
Parse the resource entry represented by a binary blob.
virtual ~AsmParsedResourceEntry()
virtual FailureOr< bool > parseAsBool() const =0
Parse the resource entry represented by a boolean.
virtual StringRef getKey() const =0
Return the key of the resource entry.
virtual FailureOr< std::string > parseAsString() const =0
Parse the resource entry represented by a human-readable string.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
MLIRContext * getContext() const
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseDimensionList(SmallVectorImpl< int64_t > &dimensions, bool allowDynamic=true, bool withTrailingX=true)=0
Parse a dimension list of a tensor or memref type.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseType(Type &result)=0
Parse a type.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
Impl(raw_ostream &os, AsmStateImpl &state)
BindingStrength
This enum is used to represent the binding strength of the enclosing context that an AffineExprStorag...
void printHexString(StringRef str)
Print a hex string, wrapped with "".
void printDenseArrayAttr(DenseArrayAttr attr)
Print a dense array attribute.
void printDenseElementsAttr(DenseElementsAttr attr, bool allowHex)
Print a dense elements attribute.
void printAttribute(Attribute attr, AttrTypeElision typeElision=AttrTypeElision::Never)
Print the given attribute or an alias.
void printDimensionList(ArrayRef< int64_t > shape)
OpPrintingFlags printerFlags
A set of flags to control the printer's behavior.
raw_ostream & os
The output stream for the printer.
void printResourceHandle(const AsmDialectResourceHandle &resource)
Print a reference to the given resource that is owned by the given dialect.
LogicalResult printAlias(Attribute attr)
Print the alias for the given attribute, return failure if no alias could be printed.
void printDialectAttribute(Attribute attr)
void interleaveComma(const Container &c, UnaryFunctor eachFn) const
void printDialectType(Type type)
void printLocation(LocationAttr loc, bool allowAlias=false)
Print the given location to the stream.
AsmStateImpl & state
An underlying assembly printer state.
void printAffineMap(AffineMap map)
void printTrailingLocation(Location loc, bool allowAlias=true)
void printAffineExprInternal(AffineExpr expr, BindingStrength enclosingTightness, function_ref< void(unsigned, bool)> printValueName=nullptr)
void printEscapedString(StringRef str)
Print an escaped string, wrapped with "".
raw_ostream & getStream()
Returns the output stream of the printer.
void printAffineExpr(AffineExpr expr, function_ref< void(unsigned, bool)> printValueName=nullptr)
void printDenseStringElementsAttr(DenseStringElementsAttr attr)
Print a dense string elements attribute.
void printAttributeImpl(Attribute attr, AttrTypeElision typeElision=AttrTypeElision::Never)
Print the given attribute without considering an alias.
void printAffineConstraint(AffineExpr expr, bool isEq)
void printDenseIntOrFPElementsAttr(DenseIntOrFPElementsAttr attr, bool allowHex)
Print a dense elements attribute.
AttrTypeElision
This enum describes the different kinds of elision for the type of an attribute when printing it.
@ May
The type may be elided when it matches the default used in the parser (for example i64 is the default...
@ Never
The type must not be elided,.
@ Must
The type must be elided.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
void printIntegerSet(IntegerSet set)
NewLineCounter newLine
A tracker for the number of new lines emitted during printing.
void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={}, bool withKeyword=false)
void printType(Type type)
Print the given type or an alias.
void printLocationInternal(LocationAttr loc, bool pretty=false, bool isTopLevel=false)
void printTypeImpl(Type type)
Print the given type.
void printNamedAttribute(NamedAttribute attr)
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual LogicalResult printAlias(Attribute attr)
Print the alias for the given attribute, return failure if no alias could be printed.
virtual void popCyclicPrinting()
Removes the element that was last inserted with a successful call to pushCyclicPrinting.
void printFunctionalType(InputRangeT &&inputs, ResultRangeT &&results)
Print the two given type ranges in a functional form.
virtual LogicalResult pushCyclicPrinting(const void *opaquePointer)
Pushes a new attribute or type in the form of a type erased pointer into an internal set.
virtual void printType(Type type)
virtual void printKeywordOrString(StringRef keyword)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
void printDimensionList(ArrayRef< int64_t > shape)
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
virtual void printResourceHandle(const AsmDialectResourceHandle &resource)
Print a handle to the given dialect resource.
virtual void printFloat(const APFloat &value)
Print the given floating point value in a stabilized form that can be roundtripped through the IR.
virtual void printNamedAttribute(NamedAttribute attr)
Print the given named attribute.
This class is used to build resource entries for use by the printer.
virtual void buildString(StringRef key, StringRef data)=0
Build a resource entry represented by the given human-readable string value.
virtual void buildBool(StringRef key, bool data)=0
Build a resource entry represented by the given bool.
virtual ~AsmResourceBuilder()
virtual void buildBlob(StringRef key, ArrayRef< char > data, uint32_t dataAlignment)=0
Build an resource entry represented by the given binary blob data.
This class represents an instance of a resource parser.
StringRef getName() const
Return the name of this parser.
virtual ~AsmResourceParser()
virtual ~AsmResourcePrinter()
static std::unique_ptr< AsmResourcePrinter > fromCallable(StringRef name, CallableT &&printFn)
Return a resource printer implemented via the given callable, whose form should match that of buildRe...
This class provides management for the lifetime of the state used when printing the IR.
DenseMap< Operation *, std::pair< unsigned, unsigned > > LocationMap
This map represents the raw locations of operations within the output stream.
detail::AsmStateImpl & getImpl()
Return an instance of the internal implementation.
void attachResourcePrinter(std::unique_ptr< AsmResourcePrinter > printer)
Attach the given resource printer to the AsmState.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources() const
Returns a map of dialect resources that were referenced when using this state to print IR.
void attachFallbackResourcePrinter(FallbackAsmResourceMap &map)
Attach resource printers to the AsmState for the fallback resources in the given map.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
AsmState(Operation *op, const OpPrintingFlags &printerFlags=OpPrintingFlags(), LocationMap *locationMap=nullptr, FallbackAsmResourceMap *map=nullptr)
Initialize the asm state at the level of the given operation.
Attributes are known-constant values of operations.
Dialect & getDialect() const
Get the dialect this attribute is registered to.
const void * getAsOpaquePointer() const
Get an opaque pointer to the attribute.
void printStripped(raw_ostream &os) const
Print the attribute without dialect wrapping.
void print(raw_ostream &os, bool elideType=false) const
Print the attribute.
bool hasTrait()
Returns true if the type was registered with a particular trait.
static Attribute getFromOpaquePointer(const void *ptr)
Construct an attribute from the opaque pointer representation.
This class represents an argument of a Block.
Location getLoc() const
Return the location for this argument.
unsigned getArgNumber() const
Returns the number of this argument.
Block represents an ordered list of Operations.
iterator_range< pred_iterator > getPredecessors()
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Block * getSinglePredecessor()
If this block has exactly one predecessor, return it.
void printAsOperand(raw_ostream &os, bool printType=true)
Print out the name of the block without printing its body.
void print(raw_ostream &os)
BlockArgListType getArguments()
bool isEntryBlock()
Return if this block is the entry block in the parent region.
bool hasNoPredecessors()
Return true if this block has no predecessors.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
MLIRContext * getContext() const
An attribute that represents a reference to a dense vector or tensor object.
An attribute that represents a reference to a dense integer vector or tensor object.
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
~DialectAsmParser() override
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
~DialectAsmPrinter() override
A collection of dialect interfaces within a context, for a given concrete interface type.
Dialect * getDialect() const
Return the dialect that this interface represents.
StringRef getNamespace() const
virtual void printAttribute(Attribute, DialectAsmPrinter &) const
Print an attribute registered to this dialect.
virtual void printType(Type, DialectAsmPrinter &) const
Print a type registered to this dialect.
Attribute getReferencedAttr() const
Returns the referenced attribute.
A fallback map containing external resources not explicitly handled by another parser/printer.
AsmResourceParser & getParserFor(StringRef key)
Return a parser than can be used for parsing entries for the given identifier key.
std::vector< std::unique_ptr< AsmResourcePrinter > > getPrinters()
Build a set of resource printers to print the resources within this map.
A symbol reference with a reference path containing a single element.
An integer set representing a conjunction of one or more affine equalities and inequalities.
unsigned getNumDims() const
unsigned getNumConstraints() const
AffineExpr getConstraint(unsigned idx) const
void print(raw_ostream &os) const
bool isEq(unsigned idx) const
Returns true if the idx^th constraint is an equality, false if it is an inequality.
unsigned getNumSymbols() const
Location objects represent source locations information in MLIR.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
OpAsmAliasResult AliasResult
virtual LogicalResult parseResource(AsmParsedResourceEntry &entry) const
Hook for parsing resource entries.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
Set of flags used to control the behavior of the various IR print methods (e.g.
bool shouldElideElementsAttr(ElementsAttr attr) const
Return if the given ElementsAttr should be elided.
std::optional< int64_t > getLargeElementsAttrLimit() const
Return the size limit for printing large ElementsAttr.
bool shouldUseNameLocAsPrefix() const
Return if the printer should use NameLocs as prefixes when printing SSA IDs.
bool shouldAssumeVerified() const
Return if operation verification should be skipped.
OpPrintingFlags & printLargeElementsAttrWithHex(int64_t largeElementLimit=100)
Enables the printing of large element attributes with a hex string.
bool shouldUseLocalScope() const
Return if the printer should use local scope when dumping the IR.
bool shouldPrintDebugInfoPrettyForm() const
Return if debug information should be printed in the pretty form.
bool shouldPrintElementsAttrWithHex(ElementsAttr attr) const
Return if the given ElementsAttr should be printed as hex string.
bool shouldPrintUniqueSSAIDs() const
Return if printer should use unique SSA IDs.
bool shouldPrintValueUsers() const
Return if the printer should print users of values.
int64_t getLargeElementsAttrHexLimit() const
Return the size limit for printing large ElementsAttr as hex string.
bool shouldPrintGenericOpForm() const
Return if operations should be printed in the generic form.
OpPrintingFlags & elideLargeResourceString(int64_t largeResourceLimit=64)
Enables the elision of large resources strings by omitting them from the dialect_resources section.
bool shouldPrintDebugInfo() const
Return if debug information should be printed.
OpPrintingFlags & elideLargeElementsAttrs(int64_t largeElementLimit=16)
Enables the elision of large elements attributes by printing a lexically valid but otherwise meaningl...
OpPrintingFlags & printNameLocAsPrefix(bool enable=true)
Print SSA IDs using their NameLoc, if provided, as prefix.
OpPrintingFlags & printValueUsers(bool enable=true)
Print users of values as comments.
OpPrintingFlags & enableDebugInfo(bool enable=true, bool prettyForm=false)
Enable or disable printing of debug information (based on enable).
OpPrintingFlags()
Initialize the printing flags with default supplied by the cl::opts above.
bool shouldSkipRegions() const
Return if regions should be skipped.
OpPrintingFlags & printGenericOpForm(bool enable=true)
Always print operations in the generic form.
OpPrintingFlags & useLocalScope(bool enable=true)
Use local scope when printing the operation.
std::optional< uint64_t > getLargeResourceStringLimit() const
Return the size limit in chars for printing large resources.
OpPrintingFlags & assumeVerified(bool enable=true)
Do not verify the operation when using custom operation printers.
OpPrintingFlags & skipRegions(bool skip=true)
Skip printing regions.
OpPrintingFlags & printUniqueSSAIDs(bool enable=true)
Print unique SSA ID numbers for values, block arguments and naming conflicts across all regions.
This is a value defined by a result of an operation.
This class provides the API for ops that are known to be isolated from above.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
void print(raw_ostream &os) const
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
bool use_empty()
Returns true if this operation has no uses.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
unsigned getNumSuccessors()
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
std::optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
unsigned getNumOperands()
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
auto getDiscardableAttrs()
Return a range of all of discardable attributes on this operation.
OperationName getName()
The name of an operation is the key identifier for it.
void print(raw_ostream &os, const OpPrintingFlags &flags={})
operand_type_range getOperandTypes()
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
LLVM_DUMP_METHOD void dumpPretty()
operand_range getOperands()
Returns an iterator on the underlying Value's.
user_range getUsers()
Returns a range of all users.
SuccessorRange getSuccessors()
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
OpaqueProperties getPropertiesStorage()
Returns the properties storage.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
iterator_range< OpIterator > getOps()
unsigned getNumArguments()
BlockArgument getArgument(unsigned i)
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
This diagnostic handler is a simple RAII class that registers and erases a diagnostic handler on a gi...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
void print(raw_ostream &os) const
Print the current type.
Dialect & getDialect() const
Get the dialect this type is registered to.
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
static Type getFromOpaquePointer(const void *pointer)
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
void walkImmediateSubElements(function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn) const
Walk all of the immediately nested sub-attributes and sub-types.
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
bool isIntOrIndex() const
Return true if this is an integer (of any signedness) or an index type.
bool isInteger() const
Return true if this is an integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
bool use_empty() const
Returns true if this value has no uses.
void print(raw_ostream &os) const
Type getType() const
Return the type of this value.
void printAsOperand(raw_ostream &os, AsmState &state) const
Print this value as if it were an operand.
user_range getUsers() const
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
SSANameState & getSSANameState()
Get the state used for SSA names.
void registerOperationLocation(Operation *op, unsigned line, unsigned col)
Register the location, line and column, within the buffer that the given operation was printed at.
auto getResourcePrinters()
Return the non-dialect resource printers.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
AliasState & getAliasState()
Get the state used for aliases.
void initializeAliases(Operation *op)
Initialize the alias state to enable the printing of aliases.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources()
Return the referenced dialect resources within the printer.
AsmStateImpl(Operation *op, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
AsmStateImpl(MLIRContext *ctx, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
DistinctState & getDistinctState()
Get the state used for distinct attribute identifiers.
DialectInterfaceCollection< OpAsmDialectInterface > & getDialectInterfaces()
Return the dialects within the context that implement OpAsmDialectInterface.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int64_t > content)
detail::StorageUserTrait::IsMutable< ConcreteType > IsMutable
This trait is used to determine if an attribute is mutable or not.
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
void printDimensionList(raw_ostream &stream, Range &&shape)
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
bool operator<(const Fraction &x, const Fraction &y)
Include the generated interface declarations.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
ParseResult parseDimensionList(OpAsmParser &parser, DenseI64ArrayAttr &dimensions)
StringRef toString(AsmResourceEntryKind kind)
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
void printDimensionList(OpAsmPrinter &printer, Operation *op, ArrayRef< int64_t > dimensions)
@ CeilDiv
RHS of ceildiv is always a constant or a symbolic expression.
@ Mul
RHS of mul is always a constant or a symbolic expression.
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
@ DimId
Dimensional identifier.
@ FloorDiv
RHS of floordiv is always a constant or a symbolic expression.
@ Constant
Constant integer.
@ SymbolId
Symbolic identifier.
llvm::SetVector< T, Vector, Set, N > SetVector
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
llvm::TypeSwitch< T, ResultT > TypeSwitch
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
AsmResourceEntryKind
This enum represents the different kinds of resource values.
@ Blob
A blob of data with an accompanying alignment.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
llvm::function_ref< Fn > function_ref
Represents a range (offset, size, and stride) where each element of the triple may be dynamic or stat...