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"
95 llvm::interleaveComma(operands,
getStream(),
100 llvm::interleaveComma(types, *
this);
108 *this << (operand ? operand.getType() : Type());
124 *this << (result ? result.getType() : Type());
136#include "mlir/IR/OpAsmAttrInterface.cpp.inc"
137#include "mlir/IR/OpAsmOpInterface.cpp.inc"
138#include "mlir/IR/OpAsmTypeInterface.cpp.inc"
142 return entry.
emitError() <<
"unknown 'resource' key '" << entry.
getKey()
143 <<
"' for dialect '" << getDialect()->getNamespace()
155struct AsmPrinterOptions {
156 llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
157 "mlir-print-elementsattrs-with-hex-if-larger",
159 "Print DenseElementsAttrs with a hex string that have "
160 "more elements than the given upper limit (use -1 to disable)")};
162 llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
163 "mlir-elide-elementsattrs-if-larger",
164 llvm::cl::desc(
"Elide ElementsAttrs with \"...\" that have "
165 "more elements than the given upper limit")};
167 llvm::cl::opt<unsigned> elideResourceStringsIfLarger{
168 "mlir-elide-resource-strings-if-larger",
170 "Elide printing value of resources if string is too long in chars.")};
172 llvm::cl::opt<bool> printDebugInfoOpt{
173 "mlir-print-debuginfo", llvm::cl::init(
false),
174 llvm::cl::desc(
"Print debug info in MLIR output")};
176 llvm::cl::opt<bool> printPrettyDebugInfoOpt{
177 "mlir-pretty-debuginfo", llvm::cl::init(
false),
178 llvm::cl::desc(
"Print pretty debug info in MLIR output")};
182 llvm::cl::opt<bool> printGenericOpFormOpt{
183 "mlir-print-op-generic", llvm::cl::init(
false),
184 llvm::cl::desc(
"Print the generic op form"), llvm::cl::Hidden};
186 llvm::cl::opt<bool> assumeVerifiedOpt{
187 "mlir-print-assume-verified", llvm::cl::init(
false),
188 llvm::cl::desc(
"Skip op verification when using custom printers"),
191 llvm::cl::opt<bool> printLocalScopeOpt{
192 "mlir-print-local-scope", llvm::cl::init(
false),
193 llvm::cl::desc(
"Print with local scope and inline information (eliding "
194 "aliases for attributes, types, and locations)")};
196 llvm::cl::opt<bool> skipRegionsOpt{
197 "mlir-print-skip-regions", llvm::cl::init(
false),
198 llvm::cl::desc(
"Skip regions when printing ops.")};
200 llvm::cl::opt<bool> printValueUsers{
201 "mlir-print-value-users", llvm::cl::init(
false),
203 "Print users of operation results and block arguments as a comment")};
205 llvm::cl::opt<bool> printUniqueSSAIDs{
206 "mlir-print-unique-ssa-ids", llvm::cl::init(
false),
207 llvm::cl::desc(
"Print unique SSA ID numbers for values, block arguments "
208 "and naming conflicts across all regions")};
210 llvm::cl::opt<bool> useNameLocAsPrefix{
211 "mlir-use-nameloc-as-prefix", llvm::cl::init(
false),
212 llvm::cl::desc(
"Print SSA IDs using NameLocs as prefixes")};
227 : printDebugInfoFlag(
false), printDebugInfoPrettyFormFlag(
false),
228 printGenericOpFormFlag(
false), skipRegionsFlag(
false),
229 assumeVerifiedFlag(
false), printLocalScope(
false),
230 printValueUsersFlag(
false), printUniqueSSAIDsFlag(
false),
231 useNameLocAsPrefix(
false) {
235 if (
clOptions->elideElementsAttrIfLarger.getNumOccurrences())
236 elementsAttrElementLimit =
clOptions->elideElementsAttrIfLarger;
237 if (
clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences())
238 elementsAttrHexElementLimit =
239 clOptions->printElementsAttrWithHexIfLarger.getValue();
240 if (
clOptions->elideResourceStringsIfLarger.getNumOccurrences())
241 resourceStringCharLimit =
clOptions->elideResourceStringsIfLarger;
242 printDebugInfoFlag =
clOptions->printDebugInfoOpt;
243 printDebugInfoPrettyFormFlag =
clOptions->printPrettyDebugInfoOpt;
244 printGenericOpFormFlag =
clOptions->printGenericOpFormOpt;
245 assumeVerifiedFlag =
clOptions->assumeVerifiedOpt;
246 printLocalScope =
clOptions->printLocalScopeOpt;
247 skipRegionsFlag =
clOptions->skipRegionsOpt;
248 printValueUsersFlag =
clOptions->printValueUsers;
249 printUniqueSSAIDsFlag =
clOptions->printUniqueSSAIDs;
250 useNameLocAsPrefix =
clOptions->useNameLocAsPrefix;
259 elementsAttrElementLimit = largeElementLimit;
265 elementsAttrHexElementLimit = largeElementLimit;
271 resourceStringCharLimit = largeResourceLimit;
279 printDebugInfoFlag = enable;
280 printDebugInfoPrettyFormFlag = prettyForm;
286 printGenericOpFormFlag = enable;
292 skipRegionsFlag = skip;
298 assumeVerifiedFlag = enable;
306 printLocalScope = enable;
312 printValueUsersFlag = enable;
319 printUniqueSSAIDsFlag = enable;
325 return elementsAttrElementLimit &&
326 *elementsAttrElementLimit <
int64_t(attr.getNumElements()) &&
327 !llvm::isa<SplatElementsAttr>(attr);
333 return (elementsAttrHexElementLimit != -1) &&
334 (elementsAttrHexElementLimit <
int64_t(attr.getNumElements())) &&
335 !llvm::isa<SplatElementsAttr>(attr);
339 useNameLocAsPrefix = enable;
345 return elementsAttrElementLimit;
350 return elementsAttrHexElementLimit;
355 return resourceStringCharLimit;
360 return printDebugInfoFlag;
365 return printDebugInfoPrettyFormFlag;
370 return printGenericOpFormFlag;
378 return assumeVerifiedFlag;
386 return printValueUsersFlag;
396 return useNameLocAsPrefix;
407struct NewLineCounter {
408 unsigned curLine = 1;
445 template <
typename Container,
typename UnaryFunctor>
447 llvm::interleaveComma(c,
os, eachFn);
494 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
507 bool withKeyword =
false);
510 bool isTopLevel =
false);
528 DenseElementType denseEltType);
552 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
582 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
584 : name(name), suffixIndex(suffixIndex), isType(isType),
585 isDeferrable(isDeferrable) {}
589 os << (isType ?
"!" :
"#") << name;
591 if (isdigit(name.back()))
598 bool isTypeAlias()
const {
return isType; }
601 bool canBeDeferred()
const {
return isDeferrable; }
607 uint32_t suffixIndex : 30;
611 bool isDeferrable : 1;
615 bool isPrinted =
false;
621class AliasInitializer {
624 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
625 llvm::BumpPtrAllocator &aliasAllocator)
626 : interfaces(interfaces), aliasAllocator(aliasAllocator),
627 aliasOS(aliasBuffer) {}
629 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
630 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
638 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
639 bool elideType =
false) {
640 return visitImpl(attr, aliases, canBeDeferred, elideType);
647 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
648 return visitImpl(type, aliases, canBeDeferred);
652 struct InProgressAliasInfo {
653 InProgressAliasInfo()
654 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
655 InProgressAliasInfo(StringRef alias)
656 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
660 if (aliasDepth !=
rhs.aliasDepth)
661 return aliasDepth <
rhs.aliasDepth;
662 if (isType !=
rhs.isType)
664 return alias <
rhs.alias;
669 std::optional<StringRef> alias;
672 unsigned aliasDepth : 30;
676 bool canBeDeferred : 1;
678 SmallVector<size_t> childIndices;
686 template <
typename T,
typename... PrintArgs>
687 std::pair<size_t, size_t>
689 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
690 bool canBeDeferred, PrintArgs &&...
printArgs);
693 void markAliasNonDeferrable(
size_t aliasIndex);
697 template <
typename T>
698 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
703 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
704 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
708 static void initializeAliases(
709 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
710 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
713 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
716 llvm::BumpPtrAllocator &aliasAllocator;
719 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
722 SmallString<32> aliasBuffer;
723 llvm::raw_svector_ostream aliasOS;
731class DummyAliasOperationPrinter :
private OpAsmPrinter {
733 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
734 AliasInitializer &initializer)
735 : printerFlags(printerFlags), initializer(initializer) {}
739 void printCustomOrGenericOp(Operation *op)
override {
741 if (printerFlags.shouldPrintDebugInfo())
742 initializer.visit(op->
getLoc(),
true);
745 if (!printerFlags.shouldPrintGenericOpForm()) {
756 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
758 if (!printerFlags.shouldSkipRegions()) {
768 if (operand && operand.getType())
775 printAttribute(attr.getValue());
777 op, [&](StringRef, Attribute &attr) { printAttribute(attr); });
783 void print(
Block *block,
bool printBlockArgs =
true,
784 bool printBlockTerminator =
true) {
787 if (printBlockArgs) {
792 if (printerFlags.shouldPrintDebugInfo())
794 initializer.visit(arg.getLoc(),
false);
802 auto range = llvm::make_range(
804 std::prev(block->
end(),
805 (!hasTerminator || printBlockTerminator) ? 0 : 1));
806 for (Operation &op : range)
807 printCustomOrGenericOp(&op);
811 void printRegion(Region ®ion,
bool printEntryBlockArgs,
812 bool printBlockTerminators,
813 bool printEmptyBlock =
false)
override {
816 if (printerFlags.shouldSkipRegions()) {
821 auto *entryBlock = ®ion.
front();
822 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
823 for (
Block &
b : llvm::drop_begin(region, 1))
827 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
828 bool omitType)
override {
831 if (printerFlags.shouldPrintDebugInfo())
833 initializer.visit(arg.
getLoc(),
false);
839 initializer.visit(type);
843 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
844 void printAttributeWithoutType(Attribute attr)
override {
845 printAttribute(attr);
847 void printNamedAttribute(NamedAttribute attr)
override {
851 LogicalResult printAlias(Attribute attr)
override {
852 initializer.visit(attr);
855 LogicalResult printAlias(Type type)
override {
856 initializer.visit(type);
861 void printOptionalLocationSpecifier(Location loc)
override {
867 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
868 ArrayRef<StringRef> elidedAttrs = {})
override {
871 if (elidedAttrs.empty()) {
872 for (
const NamedAttribute &attr : attrs)
873 printAttribute(attr.getValue());
876 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
878 for (
const NamedAttribute &attr : attrs)
879 if (!elidedAttrsSet.contains(attr.getName().strref()))
880 printAttribute(attr.getValue());
882 void printOptionalAttrDictWithKeyword(
883 ArrayRef<NamedAttribute> attrs,
884 ArrayRef<StringRef> elidedAttrs = {})
override {
885 printOptionalAttrDict(attrs, elidedAttrs);
890 raw_ostream &getStream()
const override {
return os; }
894 void printFloat(
const APFloat &)
override {}
895 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
898 void increaseIndent()
override {}
899 void decreaseIndent()
override {}
900 void printOperand(Value)
override {}
901 void printOperand(Value, raw_ostream &os)
override {
909 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
910 void printSymbolName(StringRef)
override {}
911 void printSuccessor(
Block *)
override {}
913 void shadowRegionArgs(Region &,
ValueRange)
override {}
916 const OpPrintingFlags &printerFlags;
919 AliasInitializer &initializer;
922 mutable llvm::raw_null_ostream os;
927 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
929 SmallVectorImpl<size_t> &childIndices)
930 : initializer(initializer), canBeDeferred(canBeDeferred),
931 childIndices(childIndices) {}
936 template <
typename T,
typename... PrintArgs>
937 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
938 printAndVisitNestedAliasesImpl(value,
printArgs...);
939 return maxAliasDepth;
945 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
946 if (!isa<BuiltinDialect>(attr.
getDialect())) {
950 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
951 IntegerSetAttr, UnitAttr>(attr)) {
953 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
954 printAttribute(distinctAttr.getReferencedAttr());
955 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
956 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
957 printAttribute(nestedAttr.getName());
958 printAttribute(nestedAttr.getValue());
960 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
961 for (Attribute nestedAttr : arrayAttr.getValue())
962 printAttribute(nestedAttr);
963 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
965 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
966 printAttribute(locAttr.getFallbackLocation());
967 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
968 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
969 printAttribute(locAttr.getChildLoc());
970 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
971 printAttribute(locAttr.getCallee());
972 printAttribute(locAttr.getCaller());
973 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
974 if (Attribute metadata = locAttr.getMetadata())
975 printAttribute(metadata);
976 for (Location nestedLoc : locAttr.getLocations())
977 printAttribute(nestedLoc);
982 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
983 Type attrType = typedAttr.getType();
984 if (!llvm::isa<NoneType>(attrType))
989 void printAndVisitNestedAliasesImpl(Type type) {
996 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
998 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
999 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
1000 printAttribute(memrefTy.getLayout());
1001 if (memrefTy.getMemorySpace())
1002 printAttribute(memrefTy.getMemorySpace());
1007 auto visitFn = [&](
auto element) {
1009 (void)printAlias(element);
1016 recordAliasResult(initializer.visit(type, canBeDeferred));
1020 void printAttribute(Attribute attr)
override {
1021 recordAliasResult(initializer.visit(attr, canBeDeferred));
1023 void printAttributeWithoutType(Attribute attr)
override {
1025 initializer.visit(attr, canBeDeferred,
true));
1027 void printNamedAttribute(NamedAttribute attr)
override {
1031 LogicalResult printAlias(Attribute attr)
override {
1032 printAttribute(attr);
1035 LogicalResult printAlias(Type type)
override {
1041 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1042 childIndices.push_back(aliasDepthAndIndex.second);
1043 if (aliasDepthAndIndex.first > maxAliasDepth)
1044 maxAliasDepth = aliasDepthAndIndex.first;
1049 raw_ostream &getStream()
const override {
return os; }
1054 void increaseIndent()
override {}
1055 void decreaseIndent()
override {}
1056 void printFloat(
const APFloat &)
override {}
1059 void printSymbolName(StringRef)
override {}
1060 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1062 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1063 return success(cyclicPrintingStack.insert(opaquePointer));
1066 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1070 SetVector<const void *> cyclicPrintingStack;
1073 AliasInitializer &initializer;
1079 SmallVectorImpl<size_t> &childIndices;
1082 size_t maxAliasDepth = 0;
1085 mutable llvm::raw_null_ostream os;
1093 StringRef allowedPunctChars =
"$._-") {
1094 assert(!name.empty() &&
"Shouldn't have an empty name here");
1096 auto validChar = [&](
char ch) {
1097 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1100 auto copyNameToBuffer = [&] {
1101 for (
char ch : name) {
1103 buffer.push_back(ch);
1105 buffer.push_back(
'_');
1107 buffer.append(llvm::utohexstr((
unsigned char)ch));
1114 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1115 buffer.push_back(
'_');
1121 for (
char ch : name) {
1122 if (!validChar(ch)) {
1132unsigned AliasInitializer::uniqueAliasNameIndex(
1133 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1134 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1135 if (!usedAliases.count(alias)) {
1136 usedAliases.insert(alias);
1142 size_t probeSize = probeAlias.size();
1144 if (isdigit(alias.back())) {
1145 probeAlias.push_back(
'_');
1149 if (nameCounts[probeAlias] == 0)
1150 nameCounts[probeAlias] = 1;
1154 unsigned nameIndex = nameCounts[probeAlias]++;
1155 probeAlias += llvm::utostr(nameIndex);
1156 if (!usedAliases.count(probeAlias)) {
1157 usedAliases.insert(probeAlias);
1161 probeAlias.resize(probeSize);
1167void AliasInitializer::initializeAliases(
1168 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1169 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1171 unprocessedAliases = visitedSymbols.takeVector();
1172 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1176 llvm::BumpPtrAllocator usedAliasAllocator;
1177 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1179 llvm::StringMap<unsigned> nameCounts;
1180 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1181 if (!aliasInfo.alias)
1183 StringRef alias = *aliasInfo.alias;
1184 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1185 symbolToAlias.insert(
1186 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1187 aliasInfo.canBeDeferred)});
1191void AliasInitializer::initialize(
1193 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1197 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1198 aliasPrinter.printCustomOrGenericOp(op);
1201 initializeAliases(aliases, attrTypeToAlias);
1204template <
typename T,
typename... PrintArgs>
1205std::pair<size_t, size_t> AliasInitializer::visitImpl(
1206 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1207 bool canBeDeferred, PrintArgs &&...
printArgs) {
1208 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1209 size_t aliasIndex = std::distance(aliases.begin(), it);
1213 markAliasNonDeferrable(aliasIndex);
1214 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1218 generateAlias(value, it->second, canBeDeferred);
1219 it->second.isType = std::is_base_of_v<Type, T>;
1220 it->second.canBeDeferred = canBeDeferred;
1224 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1225 size_t maxAliasDepth =
1226 printer.printAndVisitNestedAliases(value,
printArgs...);
1229 it = std::next(aliases.begin(), aliasIndex);
1232 it->second.childIndices = std::move(childAliases);
1234 it->second.aliasDepth = maxAliasDepth + 1;
1237 return {(size_t)it->second.aliasDepth, aliasIndex};
1240void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1241 auto *it = std::next(aliases.begin(), aliasIndex);
1245 if (!it->second.canBeDeferred)
1248 it->second.canBeDeferred =
false;
1251 for (
size_t childIndex : it->second.childIndices)
1252 markAliasNonDeferrable(childIndex);
1255template <
typename T>
1256void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1257 bool canBeDeferred) {
1260 OpAsmDialectInterface::AliasResult symbolInterfaceResult =
1261 OpAsmDialectInterface::AliasResult::NoAlias;
1262 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1263 OpAsmAttrInterface, OpAsmTypeInterface>;
1264 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1265 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1266 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1267 nameBuffer = std::move(aliasBuffer);
1268 assert(!nameBuffer.empty() &&
"expected valid alias name");
1272 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1273 for (
const auto &interface : interfaces) {
1274 OpAsmDialectInterface::AliasResult
result =
1275 interface.getAlias(symbol, aliasOS);
1276 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1278 nameBuffer = std::move(aliasBuffer);
1279 assert(!nameBuffer.empty() &&
"expected valid alias name");
1280 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1285 if (nameBuffer.empty())
1291 name = name.copy(aliasAllocator);
1292 alias = InProgressAliasInfo(name);
1305 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1306 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1310 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1314 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1318 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1319 printAliases(p, newLine,
false);
1323 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1324 printAliases(p, newLine,
true);
1330 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1334 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1337 llvm::BumpPtrAllocator aliasAllocator;
1341void AliasState::initialize(
1344 AliasInitializer initializer(interfaces, aliasAllocator);
1345 initializer.initialize(op, printerFlags, attrTypeToAlias);
1350 if (it == attrTypeToAlias.end())
1352 it->second.print(os);
1358 if (it == attrTypeToAlias.end())
1360 if (!it->second.isPrinted)
1363 it->second.print(os);
1369 auto filterFn = [=](
const auto &aliasIt) {
1370 return aliasIt.second.canBeDeferred() == isDeferred;
1372 for (
auto &[opaqueSymbol, alias] :
1373 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1377 if (alias.isTypeAlias()) {
1380 alias.isPrinted =
true;
1410 enum :
unsigned { NameSentinel = ~0U };
1412 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1413 SSANameState() =
default;
1418 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1421 void printOperationID(Operation *op, raw_ostream &stream)
const;
1425 ArrayRef<int> getOpResultGroups(Operation *op);
1428 BlockInfo getBlockInfo(
Block *block);
1433 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1437 void numberValuesInRegion(Region ®ion);
1438 void numberValuesInBlock(
Block &block);
1439 void numberValuesInOp(Operation &op);
1445 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1446 std::optional<int> &lookupResultNo)
const;
1449 void setValueName(Value value, StringRef name);
1453 StringRef uniqueValueName(StringRef name);
1476 llvm::ScopedHashTable<StringRef, char> usedNames;
1477 llvm::BumpPtrAllocator usedNameAllocator;
1480 unsigned nextValueID = 0;
1482 unsigned nextArgumentID = 0;
1484 unsigned nextConflictID = 0;
1488 OpPrintingFlags printerFlags;
1493 : printerFlags(printerFlags) {
1494 llvm::SaveAndRestore valueIDSaver(nextValueID);
1495 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1496 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1501 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1502 using NamingContext =
1503 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1506 llvm::BumpPtrAllocator allocator;
1509 auto *topLevelNamesScope =
1510 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1514 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1515 nextConflictID, topLevelNamesScope));
1517 numberValuesInOp(*op);
1519 while (!nameContext.empty()) {
1521 UsedNamesScopeTy *parentScope;
1525 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1526 nameContext.pop_back_val();
1528 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1529 parentScope) = nameContext.pop_back_val();
1533 while (usedNames.getCurScope() != parentScope) {
1534 usedNames.getCurScope()->~UsedNamesScopeTy();
1535 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1536 "top level parentScope must be a nullptr");
1540 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1541 UsedNamesScopeTy(usedNames);
1543 numberValuesInRegion(*region);
1547 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1548 nextArgumentID, nextConflictID,
1553 while (usedNames.getCurScope() !=
nullptr)
1554 usedNames.getCurScope()->~UsedNamesScopeTy();
1557void SSANameState::printValueID(
Value value,
bool printResultNo,
1560 stream <<
"<<NULL VALUE>>";
1564 std::optional<int> resultNo;
1565 auto lookupValue = value;
1569 if (OpResult
result = dyn_cast<OpResult>(value))
1570 getResultIDAndNumber(
result, lookupValue, resultNo);
1572 auto it = valueIDs.find(lookupValue);
1573 if (it == valueIDs.end()) {
1574 stream <<
"<<UNKNOWN SSA VALUE>>";
1579 if (it->second != NameSentinel) {
1580 stream << it->second;
1582 auto nameIt = valueNames.find(lookupValue);
1583 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1584 stream << nameIt->second;
1587 if (resultNo && printResultNo)
1588 stream <<
'#' << *resultNo;
1591void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1592 auto it = operationIDs.find(op);
1593 if (it == operationIDs.end()) {
1594 stream <<
"<<UNKNOWN OPERATION>>";
1596 stream <<
'%' << it->second;
1600ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1601 auto it = opResultGroups.find(op);
1602 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1605BlockInfo SSANameState::getBlockInfo(
Block *block) {
1606 auto it = blockNames.find(block);
1607 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1608 return it != blockNames.end() ? it->second : invalidBlock;
1611void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1612 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1614 "incorrect number of names passed in");
1616 "only KnownIsolatedFromAbove ops can shadow names");
1618 SmallVector<char, 16> nameStr;
1619 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1620 auto nameToUse = namesToUse[i];
1621 if (nameToUse ==
nullptr)
1626 llvm::raw_svector_ostream nameStream(nameStr);
1627 printValueID(nameToUse,
true, nameStream);
1630 assert(valueIDs[nameToReplace] == NameSentinel);
1633 auto name = StringRef(nameStream.str()).drop_front();
1636 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1642StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1644 return maybeNameLoc.getName();
1649void SSANameState::numberValuesInRegion(Region ®ion) {
1651 bool opAsmOpInterfaceUsed =
false;
1652 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1653 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1654 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1655 "arg not defined in current region");
1656 opAsmOpInterfaceUsed =
true;
1658 name = maybeGetValueNameFromLoc(arg, name);
1659 setValueName(arg, name);
1664 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1665 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1667 if (!opAsmOpInterfaceUsed) {
1669 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1670 interface.getAsmName(
1671 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1679 unsigned nextBlockID = 0;
1680 for (
auto &block : region) {
1683 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1684 if (blockInfoIt.second) {
1688 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1689 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1691 blockInfoIt.first->second.ordering = nextBlockID++;
1693 numberValuesInBlock(block);
1697void SSANameState::numberValuesInBlock(
Block &block) {
1701 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1702 llvm::raw_svector_ostream specialName(specialNameBuffer);
1704 if (valueIDs.count(arg))
1707 specialNameBuffer.resize(strlen(
"arg"));
1708 specialName << nextArgumentID++;
1710 StringRef specialNameStr = specialName.str();
1712 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1713 setValueName(arg, specialNameStr);
1717 for (
auto &op : block)
1718 numberValuesInOp(op);
1721void SSANameState::numberValuesInOp(Operation &op) {
1723 SmallVector<int, 2> resultGroups(1, 0);
1725 bool opAsmOpInterfaceUsed =
false;
1726 auto setResultNameFn = [&](Value
result, StringRef name) {
1727 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1728 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1729 opAsmOpInterfaceUsed =
true;
1731 name = maybeGetValueNameFromLoc(
result, name);
1732 setValueName(
result, name);
1735 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1736 resultGroups.push_back(resultNo);
1739 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1741 "getAsmBlockArgumentNames callback invoked on a block not directly "
1742 "nested under the current operation");
1743 assert(!blockNames.count(block) &&
"block numbered multiple times");
1744 SmallString<16> tmpBuffer{
"^"};
1746 if (name.data() != tmpBuffer.data()) {
1747 tmpBuffer.append(name);
1748 name = tmpBuffer.str();
1750 name = name.copy(usedNameAllocator);
1751 blockNames[block] = {-1, name};
1755 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1756 asmInterface.getAsmBlockNames(setBlockNameFn);
1757 asmInterface.getAsmResultNames(setResultNameFn);
1759 if (!opAsmOpInterfaceUsed) {
1762 bool allHaveOpAsmTypeInterface =
1764 return isa<OpAsmTypeInterface>(type);
1766 if (allHaveOpAsmTypeInterface) {
1768 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1769 interface.getAsmName(
1770 [&](StringRef name) { setResultNameFn(
result, name); });
1777 if (numResults == 0) {
1780 if (operationIDs.try_emplace(&op, nextValueID).second)
1789 setValueName(resultBegin, nameLoc.getName());
1794 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1798 if (resultGroups.size() != 1) {
1799 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1800 opResultGroups.try_emplace(&op, std::move(resultGroups));
1804void SSANameState::getResultIDAndNumber(
1805 OpResult
result, Value &lookupValue,
1806 std::optional<int> &lookupResultNo)
const {
1807 Operation *owner =
result.getOwner();
1810 int resultNo =
result.getResultNumber();
1814 auto resultGroupIt = opResultGroups.find(owner);
1815 if (resultGroupIt == opResultGroups.end()) {
1817 lookupResultNo = resultNo;
1823 ArrayRef<int> resultGroups = resultGroupIt->second;
1824 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1825 int groupResultNo = 0, groupSize = 0;
1828 if (it == resultGroups.end()) {
1829 groupResultNo = resultGroups.back();
1830 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1833 groupResultNo = *std::prev(it);
1834 groupSize = *it - groupResultNo;
1839 lookupResultNo = resultNo - groupResultNo;
1840 lookupValue = owner->
getResult(groupResultNo);
1843void SSANameState::setValueName(Value value, StringRef name) {
1846 valueIDs[value] = nextValueID++;
1850 valueIDs[value] = NameSentinel;
1851 valueNames[value] = uniqueValueName(name);
1854StringRef SSANameState::uniqueValueName(StringRef name) {
1855 SmallString<16> tmpBuffer;
1859 if (!usedNames.count(name)) {
1860 name = name.copy(usedNameAllocator);
1865 SmallString<64> probeName(name);
1866 probeName.push_back(
'_');
1868 probeName += llvm::utostr(nextConflictID++);
1869 if (!usedNames.count(probeName)) {
1870 name = probeName.str().copy(usedNameAllocator);
1873 probeName.resize(name.size() + 1);
1877 usedNames.insert(name,
char());
1887class DistinctState {
1890 uint64_t getId(DistinctAttr distinctAttr);
1893 uint64_t distinctCounter = 0;
1898uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1900 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1903 return it->getSecond();
1924 llvm_unreachable(
"unknown AsmResourceEntryKind");
1928 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1930 collection = std::make_unique<ResourceCollection>(key);
1934std::vector<std::unique_ptr<AsmResourcePrinter>>
1936 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1937 for (
auto &it : keyToResources) {
1938 ResourceCollection *collection = it.second.get();
1940 return collection->buildResources(op, builder);
1942 printers.emplace_back(
1948LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1952 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1955 resources.emplace_back(entry.
getKey(), std::move(*blob));
1962 resources.emplace_back(entry.
getKey(), *value);
1965 case AsmResourceEntryKind::String: {
1969 resources.emplace_back(entry.
getKey(), std::move(*str));
1976void FallbackAsmResourceMap::ResourceCollection::buildResources(
1977 Operation *op, AsmResourceBuilder &builder)
const {
1978 for (
const auto &entry : resources) {
1979 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1981 else if (
const auto *value = std::get_if<bool>(&entry.value))
1983 else if (
const auto *value = std::get_if<std::string>(&entry.value))
1986 llvm_unreachable(
"unknown AsmResourceEntryKind");
2000 : interfaces(op->
getContext()), nameState(op, printerFlags),
2001 printerFlags(printerFlags), locationMap(locationMap) {}
2004 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
2008 aliasState.initialize(op, printerFlags, interfaces);
2028 return llvm::make_pointee_range(externalResourcePrinters);
2038 (*locationMap)[op] = std::make_pair(line, col);
2044 return dialectResources;
2048 return success(cyclicPrintingStack.insert(opaquePointer));
2064 AliasState aliasState;
2067 SSANameState nameState;
2070 DistinctState distinctState;
2086template <
typename Range>
2090 [&stream](
const auto &dimSize) {
2091 if (ShapedType::isDynamic(dimSize))
2109 return printerFlags;
2113 auto parentThreadId = llvm::get_threadid();
2115 if (parentThreadId == llvm::get_threadid()) {
2117 diag.print(llvm::dbgs());
2118 llvm::dbgs() <<
"\n";
2126 <<
"' failed to verify and will be printed in generic form";
2130 return printerFlags;
2149 return impl->getPrinterFlags();
2153 std::unique_ptr<AsmResourcePrinter> printer) {
2154 impl->externalResourcePrinters.emplace_back(std::move(printer));
2159 return impl->getDialectResources();
2181 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2185 .Case([&](OpaqueLoc loc) {
2188 .Case([&](UnknownLoc loc) {
2196 os << loc.getFilename().getValue();
2199 if (loc.getEndColumn() == loc.getStartColumn() &&
2200 loc.getStartLine() == loc.getEndLine()) {
2201 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2204 if (loc.getStartLine() == loc.getEndLine()) {
2205 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2206 <<
" to :" << loc.getEndColumn();
2209 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2210 << loc.getEndLine() <<
':' << loc.getEndColumn();
2212 .Case([&](NameLoc loc) {
2216 auto childLoc = loc.getChildLoc();
2217 if (!llvm::isa<UnknownLoc>(childLoc)) {
2223 .Case([&](CallSiteLoc loc) {
2230 if (llvm::isa<NameLoc>(callee)) {
2231 if (llvm::isa<FileLineColLoc>(caller)) {
2249 if (
Attribute metadata = loc.getMetadata()) {
2256 printLocationInternal(loc, pretty);
2270 bool *printedHex =
nullptr) {
2275 bool isInf = apValue.isInfinity();
2276 bool isNaN = apValue.isNaN();
2277 if (!isInf && !isNaN) {
2279 apValue.toString(strValue, 6, 0,
2285 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2286 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2287 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2288 "[-+]?[0-9] regex does not match!");
2292 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2300 apValue.toString(strValue);
2303 if (strValue.str().contains(
'.')) {
2314 APInt apInt = apValue.bitcastToAPInt();
2315 apInt.toString(str, 16,
false,
2335 if (symName.empty() || !isalpha(symName.front()))
2340 symName = symName.drop_while(
2341 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2342 if (symName.empty())
2347 return symName.front() ==
'<' && symName.back() ==
'>';
2352 StringRef dialectName, StringRef symString) {
2353 os << symPrefix << dialectName;
2358 os <<
'.' << symString;
2362 os <<
'<' << symString <<
'>';
2371 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2373 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2374 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2389 printEscapedString(keyword, os);
2397 if (symbolRef.empty()) {
2398 os <<
"@<<INVALID EMPTY SYMBOL>>";
2411 os << R
"(dense_resource<__elided__>)";
2416 auto *
interface = cast<OpAsmDialectInterface>(resource.getDialect());
2422 return state.getAliasState().getAlias(attr,
os);
2426 return state.getAliasState().getAlias(type,
os);
2432 os <<
"<<NULL ATTRIBUTE>>";
2443 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2445 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2447 opaqueAttr.getAttrData());
2448 }
else if (llvm::isa<UnitAttr>(attr)) {
2451 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2452 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2458 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2464 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2465 Type intType = intAttr.getType();
2467 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2478 intAttr.getValue().print(
os, !isUnsigned);
2484 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2485 bool printedHex =
false;
2493 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2496 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2499 printAttribute(attr, AttrTypeElision::May);
2503 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2504 os <<
"affine_map<";
2505 affineMapAttr.getValue().print(
os);
2511 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2512 os <<
"affine_set<";
2513 integerSetAttr.getValue().print(
os);
2519 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2522 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2529 }
else if (
auto intOrFpEltAttr =
2530 llvm::dyn_cast<DenseTypedElementsAttr>(attr)) {
2531 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2538 Type eltType = intOrFpEltAttr.getElementType();
2539 if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
2543 cast<DenseElementType>(eltType));
2549 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2550 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2558 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2559 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2560 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2565 if (
indices.getNumElements() != 0) {
2572 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2573 stridedLayoutAttr.print(
os);
2574 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2576 printType(denseArrayAttr.getElementType());
2577 if (!denseArrayAttr.empty()) {
2583 }
else if (
auto resourceAttr =
2584 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2585 os <<
"dense_resource<";
2588 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2591 llvm::report_fatal_error(
"Unknown builtin attribute");
2595 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2596 Type attrType = typedAttr.getType();
2597 if (!llvm::isa<NoneType>(attrType)) {
2609 os << (value.getBoolValue() ?
"true" :
"false");
2619 return printEltFn(0);
2622 auto numElements = type.getNumElements();
2623 if (numElements == 0)
2631 int64_t rank = type.getRank();
2634 unsigned openBrackets = 0;
2636 auto shape = type.getShape();
2637 auto bumpCounter = [&] {
2639 ++counter[rank - 1];
2641 for (
unsigned i = rank - 1; i > 0; --i)
2642 if (counter[i] >=
shape[i]) {
2651 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2654 while (openBrackets++ < rank)
2656 openBrackets = rank;
2660 while (openBrackets-- > 0)
2666 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2675 auto type = attr.getType();
2676 auto elementType = type.getElementType();
2679 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2681 if (llvm::endianness::native == llvm::endianness::big) {
2686 DenseTypedElementsAttr::convertEndianOfArrayRefForBEmachine(
2687 rawData, convRawData, type);
2696 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2697 Type complexElementType = complexTy.getElementType();
2701 if (llvm::isa<IntegerType>(complexElementType)) {
2704 auto complexValue = *(valueIt + index);
2706 printDenseIntElement(complexValue.real(), os, complexElementType);
2708 printDenseIntElement(complexValue.imag(), os, complexElementType);
2714 auto complexValue = *(valueIt + index);
2716 printFloatValue(complexValue.real(), os);
2718 printFloatValue(complexValue.imag(), os);
2722 }
else if (elementType.isIntOrIndex()) {
2723 auto valueIt = attr.value_begin<APInt>();
2725 printDenseIntElement(*(valueIt + index), os, elementType);
2728 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2729 auto valueIt = attr.value_begin<APFloat>();
2731 printFloatValue(*(valueIt + index), os);
2737 DenseStringElementsAttr attr) {
2751 size_t bitSize = denseEltType.getDenseElementBitSize();
2752 size_t byteSize = llvm::divideCeil(bitSize,
static_cast<size_t>(CHAR_BIT));
2757 size_t offset = attr.isSplat() ? 0 : index * byteSize;
2758 ArrayRef<char> elemData = rawData.slice(offset, byteSize);
2759 Attribute elemAttr = denseEltType.convertToAttribute(elemData);
2760 printAttributeImpl(elemAttr);
2765 Type type = attr.getElementType();
2767 unsigned byteSize = bitwidth / 8;
2770 auto printElementAt = [&](
unsigned i) {
2771 APInt value(bitwidth, 0);
2773 llvm::LoadIntFromMemory(
2774 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2785 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2791 os <<
"<<NULL TYPE>>";
2803 .Case([&](OpaqueType opaqueTy) {
2805 opaqueTy.getTypeData());
2807 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2808 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2809 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2810 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2811 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2812 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2813 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2814 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2815 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2816 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2817 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2818 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2819 .Case<Float8E5M3FNUType>([&](
Type) {
os <<
"f8E5M3FNU"; })
2820 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2821 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2822 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2823 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2824 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2825 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2826 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2827 .Case([&](IntegerType integerTy) {
2828 if (integerTy.isSigned())
2830 else if (integerTy.isUnsigned())
2832 os <<
'i' << integerTy.getWidth();
2834 .Case([&](FunctionType funcTy) {
2839 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2847 .Case([&](VectorType vectorTy) {
2848 auto scalableDims = vectorTy.getScalableDims();
2850 auto vShape = vectorTy.getShape();
2851 unsigned lastDim = vShape.size();
2852 unsigned dimIdx = 0;
2853 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2854 if (!scalableDims.empty() && scalableDims[dimIdx])
2856 os << vShape[dimIdx];
2857 if (!scalableDims.empty() && scalableDims[dimIdx])
2864 .Case([&](RankedTensorType tensorTy) {
2867 if (!tensorTy.getShape().empty())
2871 if (tensorTy.getEncoding()) {
2877 .Case([&](UnrankedTensorType tensorTy) {
2882 .Case([&](MemRefType memrefTy) {
2885 if (!memrefTy.getShape().empty())
2888 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2889 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2894 if (memrefTy.getMemorySpace()) {
2904 if (memrefTy.getMemorySpace()) {
2910 .Case([&](ComplexType complexTy) {
2915 .Case([&](TupleType tupleTy) {
2918 [&](
Type type) { printType(type); });
2921 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2922 .Case<TokenType>([&](
Type) {
os <<
"token"; })
2923 .Case([&](GraphType graphTy) {
2928 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2947 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2950 os <<
" attributes";
2960 if (elidedAttrs.empty())
2961 return printFilteredAttributesFn(attrs);
2964 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2966 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2967 return !elidedAttrsSet.contains(attr.
getName().strref());
2969 if (!filteredAttrs.empty())
2970 printFilteredAttributesFn(filteredAttrs);
2977 if (llvm::isa<UnitAttr>(attr.
getValue()))
2988 std::string attrName;
2990 llvm::raw_string_ostream attrNameStr(attrName);
3000 dialect.printAttribute(attr, printer);
3009 std::string typeName;
3011 llvm::raw_string_ostream typeNameStr(typeName);
3021 dialect.printType(type, printer);
3028 llvm::printEscapedString(str,
os);
3033 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
3040 return state.pushCyclicPrinting(opaquePointer);
3056 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
3057 return impl->getStream();
3061 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3062 impl->printNewline();
3066 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3067 impl->increaseIndent();
3071 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3072 impl->decreaseIndent();
3077 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3082 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3083 impl->printType(type);
3087 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3088 impl->printAttribute(attr);
3092 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3093 return impl->printAlias(attr);
3097 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3098 return impl->printAlias(type);
3103 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3108 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3109 impl->printNamedAttribute(attr);
3113 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3118 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3120 printEscapedString(keyword,
getStream());
3125 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3130 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3131 impl->printResourceHandle(resource);
3139 return impl->pushCyclicPrinting(opaquePointer);
3156 const char *binopSpelling =
nullptr;
3159 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3161 printValueName(pos,
true);
3167 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3169 printValueName(pos,
false);
3175 os << cast<AffineConstantExpr>(expr).getValue();
3178 binopSpelling =
" + ";
3181 binopSpelling =
" * ";
3184 binopSpelling =
" floordiv ";
3187 binopSpelling =
" ceildiv ";
3190 binopSpelling =
" mod ";
3194 auto binOp = cast<AffineBinaryOpExpr>(expr);
3204 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3206 rhsConst.getValue() == -1) {
3216 os << binopSpelling;
3230 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3233 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3234 if (rrhs.getValue() == -1) {
3251 if (rrhs.getValue() < -1) {
3259 os <<
" * " << -
static_cast<uint64_t
>(rrhs.getValue());
3269 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3270 if (rhsConst.getValue() < 0) {
3273 os <<
" - " << -
static_cast<uint64_t
>(rhsConst.getValue());
3291 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3297 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3298 os <<
'd' << i <<
", ";
3307 os <<
's' << i <<
", ";
3316 [&](
AffineExpr expr) { printAffineExpr(expr); });
3323 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3324 os <<
'd' << i - 1 <<
", ";
3333 os <<
's' << i <<
", ";
3342 for (
int i = 1; i < numConstraints; ++i) {
3346 if (numConstraints >= 1)
3348 set.
isEq(numConstraints - 1));
3367 void printTopLevelOperation(
Operation *op);
3371 void printFullOpWithIndentAndLoc(
Operation *op);
3377 void printCustomOrGenericOp(
Operation *op)
override;
3379 void printGenericOp(
Operation *op,
bool printOpName)
override;
3382 void printBlockName(
Block *block);
3387 void print(
Block *block,
bool printBlockArgs =
true,
3388 bool printBlockTerminator =
true);
3391 void printValueID(
Value value,
bool printResultNo =
true,
3404 void printOptionalLocationSpecifier(
Location loc)
override {
3405 printTrailingLocation(loc);
3415 bool omitType =
false)
override;
3418 void printOperand(Value value)
override { printValueID(value); }
3419 void printOperand(Value value, raw_ostream &os)
override {
3420 printValueID(value,
true, &os);
3424 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3425 ArrayRef<StringRef> elidedAttrs = {})
override {
3426 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3428 void printOptionalAttrDictWithKeyword(
3429 ArrayRef<NamedAttribute> attrs,
3430 ArrayRef<StringRef> elidedAttrs = {})
override {
3431 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3436 void printSuccessor(
Block *successor)
override;
3440 void printSuccessorAndUseList(
Block *successor,
3444 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3445 bool printBlockTerminators,
bool printEmptyBlock)
override;
3451 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3457 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3462 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3466 void printUsersComment(Operation *op);
3469 void printUsersComment(BlockArgument arg);
3472 void printValueUsers(Value value);
3476 void printUserIDs(Operation *user,
bool prefixComma =
false);
3481 class ResourceBuilder :
public AsmResourceBuilder {
3487 using PrintFn =
function_ref<void(StringRef, ValueFn, int64_t sizeHint)>;
3489 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3490 ~ResourceBuilder()
override =
default;
3492 void buildBool(StringRef key,
bool data)
final {
3494 key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); },
3498 void buildString(StringRef key, StringRef data)
final {
3501 [&](raw_ostream &os) {
3503 llvm::printEscapedString(data, os);
3509 void buildBlob(StringRef key, ArrayRef<char> data,
3510 uint32_t dataAlignment)
final {
3513 int64_t sizeHint = 2 * int64_t(
sizeof(dataAlignment) + data.size()) + 4;
3516 [&](raw_ostream &os) {
3519 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3522 StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3523 sizeof(dataAlignment)))
3524 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3534 void printFileMetadataDictionary(Operation *op);
3540 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3548 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3552void OperationPrinter::printTopLevelOperation(Operation *op) {
3554 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3557 printFullOpWithIndentAndLoc(op);
3564 printFileMetadataDictionary(op);
3567void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3568 bool sawMetadataEntry =
false;
3569 auto checkAddMetadataDict = [&] {
3570 if (!std::exchange(sawMetadataEntry,
true))
3571 os << newLine <<
"{-#" << newLine;
3575 printResourceFileMetadata(checkAddMetadataDict, op);
3578 if (sawMetadataEntry)
3579 os << newLine <<
"#-}" << newLine;
3582void OperationPrinter::printResourceFileMetadata(
3583 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3585 bool hadResource =
false;
3586 bool needResourceComma =
false;
3587 bool needEntryComma =
false;
3588 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3589 auto &&...providerArgs) {
3590 bool hadEntry =
false;
3591 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn,
3593 checkAddMetadataDict();
3595 std::string resourceStr;
3596 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3597 std::optional<uint64_t> charLimit =
3599 if (charLimit.has_value()) {
3601 if (charLimit.value() == 0)
3606 if (sizeHint >= 0 && uint64_t(sizeHint) > charLimit.value())
3609 llvm::raw_string_ostream ss(resourceStr);
3613 if (resourceStr.size() > charLimit.value())
3617 valueFn = printResourceStr;
3621 if (!std::exchange(hadResource,
true)) {
3622 if (needResourceComma)
3623 os <<
"," << newLine;
3624 os <<
" " << dictName <<
"_resources: {" << newLine;
3627 if (!std::exchange(hadEntry,
true)) {
3629 os <<
"," << newLine;
3630 os <<
" " << name <<
": {" << newLine;
3632 os <<
"," << newLine;
3640 ResourceBuilder entryBuilder(printFn);
3641 provider.buildResources(op, providerArgs..., entryBuilder);
3643 needEntryComma |= hadEntry;
3645 os << newLine <<
" }";
3652 StringRef name = interface.getDialect()->getNamespace();
3653 auto it = dialectResources.find(interface.getDialect());
3654 if (it != dialectResources.end())
3655 processProvider(
"dialect", name, interface, it->second);
3657 processProvider(
"dialect", name, interface,
3661 os << newLine <<
" }";
3665 needEntryComma =
false;
3666 needResourceComma = hadResource;
3667 hadResource =
false;
3669 processProvider(
"external", printer.getName(), printer);
3671 os << newLine <<
" }";
3679void OperationPrinter::printRegionArgument(BlockArgument arg,
3680 ArrayRef<NamedAttribute> argAttrs,
3687 printOptionalAttrDict(argAttrs);
3689 printTrailingLocation(arg.
getLoc(),
false);
3692void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3696 os.indent(currentIndent);
3698 printTrailingLocation(op->
getLoc());
3700 printUsersComment(op);
3703void OperationPrinter::printFullOp(Operation *op) {
3705 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3706 printValueID(op->
getResult(resultNo),
false);
3707 if (resultCount > 1)
3708 os <<
':' << resultCount;
3712 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3713 if (!resultGroups.empty()) {
3716 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3717 printResultGroup(resultGroups[i],
3718 resultGroups[i + 1] - resultGroups[i]);
3721 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3724 printResultGroup(0, numResults);
3730 printCustomOrGenericOp(op);
3733void OperationPrinter::printUsersComment(Operation *op) {
3737 printOperationID(op);
3738 }
else if (numResults && op->
use_empty()) {
3740 }
else if (numResults && !op->
use_empty()) {
3743 unsigned usedInNResults = 0;
3744 unsigned usedInNOperations = 0;
3745 SmallPtrSet<Operation *, 1> userSet;
3746 for (Operation *user : op->
getUsers()) {
3747 if (userSet.insert(user).second) {
3748 ++usedInNOperations;
3749 usedInNResults += user->getNumResults();
3754 bool exactlyOneUniqueUse =
3755 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3756 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3757 bool shouldPrintBrackets = numResults > 1;
3758 auto printOpResult = [&](OpResult opResult) {
3759 if (shouldPrintBrackets)
3761 printValueUsers(opResult);
3762 if (shouldPrintBrackets)
3766 interleaveComma(op->
getResults(), printOpResult);
3770void OperationPrinter::printUsersComment(BlockArgument arg) {
3776 os <<
" is used by ";
3777 printValueUsers(arg);
3782void OperationPrinter::printValueUsers(Value value) {
3788 SmallPtrSet<Operation *, 1> userSet;
3790 if (userSet.insert(user).second)
3791 printUserIDs(user, index);
3795void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3800 printOperationID(user);
3803 [
this](Value
result) { printValueID(result); });
3807void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3813 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3818 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3823 if (name.count(
'.') == 1)
3824 name.consume_front((defaultDialectStack.back() +
".").str());
3828 opPrinter(op, *
this);
3835 printGenericOp(op,
true);
3838void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3842 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3849 [&](
Block *successor) { printBlockName(successor); });
3863 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3864 printRegion(region, true,
3877void OperationPrinter::printBlockName(
Block *block) {
3881void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3882 bool printBlockTerminator) {
3884 if (printBlockArgs) {
3885 os.indent(currentIndent);
3886 printBlockName(block);
3891 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3894 printType(arg.getType());
3896 printTrailingLocation(arg.getLoc(), false);
3904 os <<
" // block is not in a region!";
3907 os <<
" // no predecessors";
3910 printBlockName(pred);
3914 SmallVector<BlockInfo, 4> predIDs;
3917 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3918 return lhs.ordering <
rhs.ordering;
3921 os <<
" // " << predIDs.size() <<
" preds: ";
3923 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3928 currentIndent += indentWidth;
3932 os.indent(currentIndent);
3933 printUsersComment(arg);
3937 bool hasTerminator =
3939 auto range = llvm::make_range(
3941 std::prev(block->
end(),
3942 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3943 for (
auto &op : range) {
3944 printFullOpWithIndentAndLoc(&op);
3947 currentIndent -= indentWidth;
3950void OperationPrinter::printValueID(Value value,
bool printResultNo,
3951 raw_ostream *streamOverride)
const {
3953 streamOverride ? *streamOverride : os);
3956void OperationPrinter::printOperationID(Operation *op,
3957 raw_ostream *streamOverride)
const {
3958 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3962void OperationPrinter::printSuccessor(
Block *successor) {
3963 printBlockName(successor);
3966void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3968 printBlockName(successor);
3969 if (succOperands.empty())
3973 interleaveComma(succOperands,
3974 [
this](Value operand) { printValueID(operand); });
3976 interleaveComma(succOperands,
3981void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
3982 bool printBlockTerminators,
3983 bool printEmptyBlock) {
3988 os <<
"{" << newLine;
3989 if (!region.
empty()) {
3990 llvm::scope_exit restoreDefaultDialect(
3991 [&]() { defaultDialectStack.pop_back(); });
3992 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
3993 defaultDialectStack.push_back(iface.getDefaultDialect());
3995 defaultDialectStack.push_back(
"");
3997 auto *entryBlock = ®ion.
front();
4001 bool shouldAlwaysPrintBlockHeader =
4002 (printEmptyBlock && entryBlock->empty()) ||
4003 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
4004 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
4005 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
4008 os.indent(currentIndent) <<
"}";
4011void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
4014 os <<
"<<NULL AFFINE MAP>>";
4017 AffineMap map = mapAttr.getValue();
4019 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4020 unsigned index = isSymbol ? numDims + pos : pos;
4021 assert(index < operands.size());
4024 printValueID(operands[index]);
4029 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
4030 printAffineExpr(expr, printValueName);
4034void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
4037 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4039 return printValueID(dimOperands[pos]);
4041 printValueID(symOperands[pos]);
4044 printAffineExpr(expr, printValueName);
4053 os <<
"<<NULL ATTRIBUTE>>";
4058 print(os, state, elideType);
4064 : AttrTypeElision::Never);
4068 print(llvm::errs());
4069 llvm::errs() <<
"\n";
4074 os <<
"<<NULL ATTRIBUTE>>";
4083 uint64_t posPrior = os.tell();
4085 dialect.printAttribute(*
this, printer);
4086 if (posPrior != os.tell())
4095 os <<
"<<NULL ATTRIBUTE>>";
4105 os <<
"<<NULL TYPE>>";
4117 print(llvm::errs());
4118 llvm::errs() <<
"\n";
4122 print(llvm::errs());
4123 llvm::errs() <<
"\n";
4127 print(llvm::errs());
4128 llvm::errs() <<
"\n";
4133 os <<
"<<NULL AFFINE EXPR>>";
4141 print(llvm::errs());
4142 llvm::errs() <<
"\n";
4147 os <<
"<<NULL AFFINE MAP>>";
4162 os <<
"<<NULL VALUE>>";
4167 return op->
print(os, flags);
4170 os <<
"<block argument> of type '" << arg.
getType()
4175 os <<
"<<NULL VALUE>>";
4180 return op->
print(os, state);
4184 os <<
"<block argument> of type '" << arg.
getType()
4195 llvm::errs() <<
"\n";
4226 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4229 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4231 os <<
"<<UNKNOWN SSA VALUE>>";
4247 OperationPrinter printer(os, state.
getImpl());
4250 printer.printTopLevelOperation(
this);
4252 printer.printFullOpWithIndentAndLoc(
this);
4258 llvm::errs() <<
"\n";
4263 llvm::errs() <<
"\n";
4269 os <<
"<<UNLINKED BLOCK>>\n";
4280 OperationPrinter(os, state.
getImpl()).print(
this);
4289 os <<
"<<UNLINKED BLOCK>>\n";
4296 OperationPrinter printer(os, state.
getImpl());
4297 printer.printBlockName(
this);
4312 if (dimensions.empty())
4315 if (dimensions.empty())
4325 <<
"Failed parsing dimension list.";
4336 <<
"Failed parsing dimension list.";
4338 if (shapeArr.empty()) {
4340 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4341 "must be denoted by \"[]\".";
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
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
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)
static const llvm::fltSemantics * getFloatSemantics(TruncfSrcElemTypes etype)
Float semantics the element type attributes of xevm.truncf and xevm.extf stand for.
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.
unsigned currentIndent
This is the current indentation level for nested structures.
void printAttribute(Attribute attr, AttrTypeElision typeElision=AttrTypeElision::Never)
Print the given attribute or an alias.
void printDimensionList(ArrayRef< int64_t > shape)
void printTypeFirstDenseElementsAttr(DenseElementsAttr attr, DenseElementType denseEltType)
Print a dense elements attribute using the type-first syntax and the DenseElementTypeInterface,...
OpPrintingFlags printerFlags
A set of flags to control the printer's behavior.
void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
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 decreaseIndent()
Decrease indentation.
static const unsigned indentWidth
The number of spaces used as an indent.
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)
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 printDenseTypedElementsAttr(DenseTypedElementsAttr attr, bool allowHex)
Print a dense elements attribute in the literal-first syntax.
void printNamedAttribute(NamedAttribute attr)
void increaseIndent()
Increase indentation.
virtual void decreaseIndent()
Decrease indentation.
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.
virtual void increaseIndent()
Increase indentation.
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.
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
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.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
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.
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.
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 printOperands(OperandRange operands)
Print a comma separated range of operation operands out of line to avoid instantiating the range iter...
void printOperandTypes(ValueTypeRange< OperandRange > types)
Print the types of a comma separated range of operation operands.
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
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.
This class implements the operand iterators for the Operation class.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
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()
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.
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
unsigned getNumOperands()
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
OperationName getName()
The name of an operation is the key identifier for it.
void print(raw_ostream &os, const OpPrintingFlags &flags={})
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.
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 implements iteration on the types of a given range of values.
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.
static 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
std::conditional_t< std::is_floating_point_v< T >, std::complex< T >, NonFloatComplex< T > > Complex
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...