[Mlir-commits] [mlir] 09f8e3d - [mlir][LLVMIR] Bound import diagnostics and share one slot tracker (#229956)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Oct 8 13:54:41 PDT 2026
Author: Bruno Cardoso Lopes
Date: 2026-10-08T13:54:36-07:00
New Revision: 09f8e3deec40458dc748a3e1c148a54848da9d3d
URL: https://github.com/llvm/llvm-project/commit/09f8e3deec40458dc748a3e1c148a54848da9d3d
DIFF: https://github.com/llvm/llvm-project/commit/09f8e3deec40458dc748a3e1c148a54848da9d3d.diff
LOG: [mlir][LLVMIR] Bound import diagnostics and share one slot tracker (#229956)
Import diagnostics render LLVM entities unbounded: a global prints its
entire initializer (a merged vtable reaches megabytes), and every
rendering builds its own ModuleSlotTracker, whose module walk makes a
per-instruction diagnostic quadratic in module size. To the scale we
link and use the LLVM IR dialect, this has bitten us many times
downstream, usually leading to OOM's and other silly behaviors from
something that isn't supported anyways. This solution has helped us
finding and fixing a lot of missing attributes, which will be
contributed soon.
Cap each rendering at 256 characters and print globals by name only,
diagnostics only need to identify the entity. Share one lazily created
tracker across the import instead: printing through it numbers exactly
like the per-call tracker, the module is never mutated during import so
slots stay valid, and each print establishes its own function context.
Thread the tracker through the module-flag converters so every
diagnostic uses the same numbering.
Assisted-by: Muse Code (Muse).
---------
Co-authored-by: Bruno Cardoso Lopes <bruno.cardosolopes at gmail.com>
Added:
Modified:
mlir/include/mlir/Target/LLVMIR/ModuleImport.h
mlir/lib/Target/LLVMIR/ModuleImport.cpp
mlir/test/Target/LLVMIR/Import/function-metadata.ll
mlir/test/Target/LLVMIR/Import/global-variables.ll
mlir/test/Target/LLVMIR/Import/import-failure.ll
Removed:
################################################################################
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 3bb024a88f283c..ab46245b040d09 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -24,6 +24,7 @@
namespace llvm {
class BasicBlock;
+class ModuleSlotTracker;
class CallBase;
class DbgVariableIntrinsic;
class Function;
@@ -51,6 +52,7 @@ class ModuleImport {
ModuleImport(ModuleOp mlirModule, std::unique_ptr<llvm::Module> llvmModule,
bool emitExpensiveWarnings, bool importEmptyDICompositeTypes,
bool preferUnregisteredIntrinsics, bool importStructsAsLiterals);
+ ~ModuleImport();
/// Calls the LLVMImportInterface initialization that queries the registered
/// dialect interfaces for the supported LLVM IR intrinsics and metadata kinds
@@ -315,6 +317,13 @@ class ModuleImport {
}
private:
+ /// Renders `value` into a bounded string for a diagnostic.
+ std::string renderValue(const llvm::Value &value);
+ /// Renders `node` into a bounded string for a diagnostic.
+ std::string renderMetadata(const llvm::Metadata *node);
+ /// Shared slot tracker for diagnostics, created on first use.
+ llvm::ModuleSlotTracker &getDiagSlotTracker();
+
/// Clears the accumulated state before processing a new region.
void clearRegionState() {
valueMapping.clear();
@@ -539,6 +548,13 @@ class ModuleImport {
std::unique_ptr<detail::DebugImporter> debugImporter;
/// Loop annotation importer.
std::unique_ptr<detail::LoopAnnotationImporter> loopAnnotationImporter;
+ /// Slot tracker shared by every diagnostic that renders an LLVM entity.
+ /// Metadata::print and Value::print each construct their own tracker when
+ /// not given one, and building one walks the module, so a per-call tracker
+ /// makes a per-instruction diagnostic quadratic in module size. Sharing one
+ /// makes that walk a per-import cost instead. Created lazily, so an import
+ /// that renders nothing never pays for it at all.
+ std::unique_ptr<llvm::ModuleSlotTracker> diagSlotTracker;
/// An option to control if expensive but uncritical diagnostics should be
/// emitted. Avoids generating warnings for unhandled debug intrinsics and
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index c51d03fca1753e..0223c1e3343c7f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -41,6 +41,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/LogicalResult.h"
#include "llvm/Support/ModRef.h"
@@ -52,25 +53,61 @@ using namespace mlir::LLVM::detail;
#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
-// Utility to print an LLVM value as a string for passing to emitError().
-// FIXME: Diagnostic should be able to natively handle types that have
-// operator << (raw_ostream&) defined.
-static std::string diag(const llvm::Value &value) {
+/// Upper bound on the characters a diagnostic renders for an LLVM entity.
+/// One rendering is unbounded by nature: a GlobalVariable prints its entire
+/// initializer, and a node with long MDStrings or large inline constants
+/// prints them whole. On a merged library a single unbounded diagnostic
+/// reaches tens of megabytes, so every rendering path below truncates its
+/// output. Diagnostics only need to identify the entity; the full form is
+/// in the input being imported.
+static constexpr size_t kMaxDiagLength = 256;
+
+static std::string truncateDiag(std::string str) {
+ if (str.size() <= kMaxDiagLength)
+ return str;
+ str.resize(kMaxDiagLength);
+ str += "... <truncated>";
+ return str;
+}
+
+/// Prints a metadata node through a caller-provided tracker so module-flag
+/// conversion shares the importer's tracker instead of building one per call.
+static std::string renderMetadataWithTracker(const llvm::Metadata *node,
+ llvm::ModuleSlotTracker &tracker,
+ const llvm::Module *module) {
std::string str;
llvm::raw_string_ostream os(str);
- os << value;
- return str;
+ node->print(os, tracker, module, /*IsForDebug=*/true);
+ return truncateDiag(std::move(str));
+}
+
+llvm::ModuleSlotTracker &ModuleImport::getDiagSlotTracker() {
+ // Printing through a caller-provided tracker numbers exactly like the
+ // per-call tracker Metadata::print and Value::print would construct, but
+ // the tracker's lazy module pre-pass is paid once per import instead of
+ // once per rendering.
+ if (!diagSlotTracker)
+ diagSlotTracker =
+ std::make_unique<llvm::ModuleSlotTracker>(llvmModule.get());
+ return *diagSlotTracker;
}
-// Utility to print an LLVM metadata node as a string for passing
-// to emitError(). The module argument is needed to print the nodes
-// canonically numbered.
-static std::string diagMD(const llvm::Metadata *node,
- const llvm::Module *module) {
+std::string ModuleImport::renderValue(const llvm::Value &value) {
std::string str;
llvm::raw_string_ostream os(str);
- node->print(os, module, /*IsForDebug=*/true);
- return str;
+ // A GlobalValue renders its full definition. For a merged vtable or string
+ // table that is megabytes, so print globals by name only.
+ if (const auto *global = llvm::dyn_cast<llvm::GlobalValue>(&value)) {
+ global->printAsOperand(os, /*PrintType=*/false, getDiagSlotTracker());
+ return truncateDiag(std::move(str));
+ }
+ value.print(os, getDiagSlotTracker());
+ return truncateDiag(std::move(str));
+}
+
+std::string ModuleImport::renderMetadata(const llvm::Metadata *node) {
+ return renderMetadataWithTracker(node, getDiagSlotTracker(),
+ llvmModule.get());
}
/// Returns the name of the global_ctors global variables.
@@ -284,6 +321,8 @@ getTopologicallySortedBlocks(ArrayRef<llvm::BasicBlock *> basicBlocks) {
return blocks;
}
+ModuleImport::~ModuleImport() = default;
+
ModuleImport::ModuleImport(ModuleOp mlirModule,
std::unique_ptr<llvm::Module> llvmModule,
bool emitExpensiveWarnings,
@@ -367,16 +406,15 @@ LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
const auto *memberNode =
dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
if (!memberNode) {
- emitError(loc) << "operand '" << 2 * pairNum + 1 << "' must be MDNode: "
- << diagMD(node, llvmModule.get());
+ emitError(loc) << "operand '" << 2 * pairNum + 1
+ << "' must be MDNode: " << renderMetadata(node);
return false;
}
int64_t offset = 0;
if (2 * pairNum + 2 >= numOperands) {
// Allow for optional 0 offset in 2-operand nodes.
if (numOperands != 2) {
- emitError(loc) << "missing member offset: "
- << diagMD(node, llvmModule.get());
+ emitError(loc) << "missing member offset: " << renderMetadata(node);
return false;
}
} else {
@@ -384,8 +422,7 @@ LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
node->getOperand(2 * pairNum + 2));
if (!offsetCI) {
emitError(loc) << "operand '" << 2 * pairNum + 2
- << "' must be ConstantInt: "
- << diagMD(node, llvmModule.get());
+ << "' must be ConstantInt: " << renderMetadata(node);
return false;
}
offset = offsetCI->getZExtValue();
@@ -441,7 +478,7 @@ LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
if (!isConstantCI) {
emitError(loc) << "operand '3' must be ConstantInt: "
- << diagMD(node, llvmModule.get());
+ << renderMetadata(node);
return false;
}
isConst = isConstantCI->getValue()[0];
@@ -488,8 +525,8 @@ LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
// and we have a cycle in the graph. Cycles are not allowed in TBAA
// graphs.
if (!seen.insert(current).second)
- return emitError(loc) << "has cycle in TBAA graph: "
- << diagMD(current, llvmModule.get());
+ return emitError(loc)
+ << "has cycle in TBAA graph: " << renderMetadata(current);
continue;
}
@@ -533,7 +570,7 @@ LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
}
return emitError(loc) << "unsupported TBAA node format: "
- << diagMD(current, llvmModule.get());
+ << renderMetadata(current);
}
return success();
}
@@ -543,7 +580,7 @@ ModuleImport::processAccessGroupMetadata(const llvm::MDNode *node) {
Location loc = mlirModule.getLoc();
if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
return emitError(loc) << "unsupported access group node: "
- << diagMD(node, llvmModule.get());
+ << renderMetadata(node);
return success();
}
@@ -597,11 +634,11 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
// node before.
if (!verifySelfRefOrString(scope) || !domain ||
!verifyDescription(scope, 2))
- return emitError(loc) << "unsupported alias scope node: "
- << diagMD(scope, llvmModule.get());
+ return emitError(loc)
+ << "unsupported alias scope node: " << renderMetadata(scope);
if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 2))
- return emitError(loc) << "unsupported alias domain node: "
- << diagMD(domain, llvmModule.get());
+ return emitError(loc)
+ << "unsupported alias domain node: " << renderMetadata(domain);
if (aliasScopeMapping.contains(scope))
continue;
@@ -690,11 +727,13 @@ static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule,
/// something else is found.
static llvm::MDTuple *getTwoElementMDTuple(ModuleOp mlirModule,
const llvm::Module *llvmModule,
- const llvm::MDOperand &md) {
+ const llvm::MDOperand &md,
+ llvm::ModuleSlotTracker &tracker) {
auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
if (!tupleEntry || tupleEntry->getNumOperands() != 2)
emitWarning(mlirModule.getLoc())
- << "expected 2-element tuple metadata: " << diagMD(md, llvmModule);
+ << "expected 2-element tuple metadata: "
+ << renderMetadataWithTracker(md, tracker, llvmModule);
return tupleEntry;
}
@@ -703,8 +742,10 @@ static llvm::MDTuple *getTwoElementMDTuple(ModuleOp mlirModule,
/// `matchKey` is
diff erent from the tuple's key.
static llvm::ConstantAsMetadata *getConstantMDFromKeyValueTuple(
ModuleOp mlirModule, const llvm::Module *llvmModule,
- const llvm::MDOperand &md, StringRef matchKey, bool optional = false) {
- llvm::MDTuple *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, md);
+ const llvm::MDOperand &md, StringRef matchKey,
+ llvm::ModuleSlotTracker &tracker, bool optional = false) {
+ llvm::MDTuple *tupleEntry =
+ getTwoElementMDTuple(mlirModule, llvmModule, md, tracker);
if (!tupleEntry)
return nullptr;
auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
@@ -712,7 +753,8 @@ static llvm::ConstantAsMetadata *getConstantMDFromKeyValueTuple(
if (!optional)
emitWarning(mlirModule.getLoc())
<< "expected '" << matchKey << "' key, but found: "
- << diagMD(tupleEntry->getOperand(0), llvmModule);
+ << renderMetadataWithTracker(tupleEntry->getOperand(0), tracker,
+ llvmModule);
return nullptr;
}
@@ -725,9 +767,10 @@ static llvm::ConstantAsMetadata *getConstantMDFromKeyValueTuple(
static FailureOr<uint64_t>
convertInt64FromKeyValueTuple(ModuleOp mlirModule,
const llvm::Module *llvmModule,
- const llvm::MDOperand &md, StringRef matchKey) {
- llvm::ConstantAsMetadata *valMD =
- getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey);
+ const llvm::MDOperand &md, StringRef matchKey,
+ llvm::ModuleSlotTracker &tracker) {
+ llvm::ConstantAsMetadata *valMD = getConstantMDFromKeyValueTuple(
+ mlirModule, llvmModule, md, matchKey, tracker);
if (!valMD)
return failure();
@@ -736,14 +779,16 @@ convertInt64FromKeyValueTuple(ModuleOp mlirModule,
emitWarning(mlirModule.getLoc())
<< "expected integer metadata value for key '" << matchKey
- << "': " << diagMD(md, llvmModule);
+ << "': " << renderMetadataWithTracker(md, tracker, llvmModule);
return failure();
}
static std::optional<ProfileSummaryFormatKind>
convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,
- const llvm::MDOperand &formatMD) {
- auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, formatMD);
+ const llvm::MDOperand &formatMD,
+ llvm::ModuleSlotTracker &tracker) {
+ auto *tupleEntry =
+ getTwoElementMDTuple(mlirModule, llvmModule, formatMD, tracker);
if (!tupleEntry)
return std::nullopt;
@@ -751,7 +796,8 @@ convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,
if (!keyMD || keyMD->getString() != "ProfileFormat") {
emitWarning(mlirModule.getLoc())
<< "expected 'ProfileFormat' key: "
- << diagMD(tupleEntry->getOperand(0), llvmModule);
+ << renderMetadataWithTracker(tupleEntry->getOperand(0), tracker,
+ llvmModule);
return std::nullopt;
}
@@ -766,7 +812,7 @@ convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,
if (!valMD) {
emitWarning(mlirModule.getLoc())
<< "expected string metadata value for key 'ProfileFormat': "
- << diagMD(valueMD, llvmModule);
+ << renderMetadataWithTracker(valueMD, tracker, llvmModule);
return std::nullopt;
}
std::optional<ProfileSummaryFormatKind> fmtKind =
@@ -775,7 +821,7 @@ convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,
emitWarning(mlirModule.getLoc())
<< "expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
"but found: "
- << diagMD(valMD, llvmModule);
+ << renderMetadataWithTracker(valMD, tracker, llvmModule);
return std::nullopt;
}
@@ -785,8 +831,10 @@ convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,
static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
convertProfileSummaryDetailed(ModuleOp mlirModule,
const llvm::Module *llvmModule,
- const llvm::MDOperand &summaryMD) {
- auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, summaryMD);
+ const llvm::MDOperand &summaryMD,
+ llvm::ModuleSlotTracker &tracker) {
+ auto *tupleEntry =
+ getTwoElementMDTuple(mlirModule, llvmModule, summaryMD, tracker);
if (!tupleEntry)
return failure();
@@ -794,7 +842,8 @@ convertProfileSummaryDetailed(ModuleOp mlirModule,
if (!keyMD || keyMD->getString() != "DetailedSummary") {
emitWarning(mlirModule.getLoc())
<< "expected 'DetailedSummary' key: "
- << diagMD(tupleEntry->getOperand(0), llvmModule);
+ << renderMetadataWithTracker(tupleEntry->getOperand(0), tracker,
+ llvmModule);
return failure();
}
@@ -802,7 +851,8 @@ convertProfileSummaryDetailed(ModuleOp mlirModule,
if (!entriesMD) {
emitWarning(mlirModule.getLoc())
<< "expected tuple value for 'DetailedSummary' key: "
- << diagMD(tupleEntry->getOperand(1), llvmModule);
+ << renderMetadataWithTracker(tupleEntry->getOperand(1), tracker,
+ llvmModule);
return failure();
}
@@ -812,7 +862,7 @@ convertProfileSummaryDetailed(ModuleOp mlirModule,
if (!entryMD || entryMD->getNumOperands() != 3) {
emitWarning(mlirModule.getLoc())
<< "'DetailedSummary' entry expects 3 operands: "
- << diagMD(entry, llvmModule);
+ << renderMetadataWithTracker(entry, tracker, llvmModule);
return failure();
}
@@ -822,7 +872,7 @@ convertProfileSummaryDetailed(ModuleOp mlirModule,
if (!op0 || !op1 || !op2) {
emitWarning(mlirModule.getLoc())
<< "expected only integer entries in 'DetailedSummary': "
- << diagMD(entry, llvmModule);
+ << renderMetadataWithTracker(entry, tracker, llvmModule);
return failure();
}
@@ -836,15 +886,14 @@ convertProfileSummaryDetailed(ModuleOp mlirModule,
return detailedSummary;
}
-static Attribute
-convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
- const llvm::Module *llvmModule,
- llvm::MDTuple *mdTuple) {
+static Attribute convertProfileSummaryModuleFlagValue(
+ ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple,
+ llvm::ModuleSlotTracker &tracker) {
unsigned profileNumEntries = mdTuple->getNumOperands();
if (profileNumEntries < 8) {
emitWarning(mlirModule.getLoc())
<< "expected at 8 entries in 'ProfileSummary': "
- << diagMD(mdTuple, llvmModule);
+ << renderMetadataWithTracker(mdTuple, tracker, llvmModule);
return nullptr;
}
@@ -857,7 +906,8 @@ convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
if (summayIdx + 1 >= profileNumEntries) {
emitWarning(mlirModule.getLoc())
<< "the last summary entry is '" << matchKey
- << "', expected 'DetailedSummary': " << diagMD(md, llvmModule);
+ << "', expected 'DetailedSummary': "
+ << renderMetadataWithTracker(md, tracker, llvmModule);
return failure();
}
@@ -868,12 +918,13 @@ convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
[&](const llvm::MDOperand &md,
StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
if (!getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey,
+ tracker,
/*optional=*/true))
return FailureOr<std::optional<uint64_t>>(std::nullopt);
if (checkOptionalPosition(md, matchKey).failed())
return failure();
- FailureOr<uint64_t> val =
- convertInt64FromKeyValueTuple(mlirModule, llvmModule, md, matchKey);
+ FailureOr<uint64_t> val = convertInt64FromKeyValueTuple(
+ mlirModule, llvmModule, md, matchKey, tracker);
if (failed(val))
return failure();
return val;
@@ -882,7 +933,8 @@ convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
auto getOptDoubleValue = [&](const llvm::MDOperand &md,
StringRef matchKey) -> FailureOr<FloatAttr> {
auto *valMD = getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md,
- matchKey, /*optional=*/true);
+ matchKey, tracker,
+ /*optional=*/true);
if (!valMD)
return FloatAttr{};
if (auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
@@ -893,46 +945,50 @@ convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
}
emitWarning(mlirModule.getLoc())
<< "expected double metadata value for key '" << matchKey
- << "': " << diagMD(md, llvmModule);
+ << "': " << renderMetadataWithTracker(md, tracker, llvmModule);
return failure();
};
// Build ModuleFlagProfileSummaryAttr by sequentially fetching elements in
// a fixed order: format, total count, etc.
std::optional<ProfileSummaryFormatKind> format = convertProfileSummaryFormat(
- mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
+ mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), tracker);
if (!format.has_value())
return nullptr;
FailureOr<uint64_t> totalCount = convertInt64FromKeyValueTuple(
- mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "TotalCount");
+ mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "TotalCount",
+ tracker);
if (failed(totalCount))
return nullptr;
FailureOr<uint64_t> maxCount = convertInt64FromKeyValueTuple(
- mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "MaxCount");
+ mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "MaxCount",
+ tracker);
if (failed(maxCount))
return nullptr;
FailureOr<uint64_t> maxInternalCount = convertInt64FromKeyValueTuple(
mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
- "MaxInternalCount");
+ "MaxInternalCount", tracker);
if (failed(maxInternalCount))
return nullptr;
FailureOr<uint64_t> maxFunctionCount = convertInt64FromKeyValueTuple(
mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
- "MaxFunctionCount");
+ "MaxFunctionCount", tracker);
if (failed(maxFunctionCount))
return nullptr;
FailureOr<uint64_t> numCounts = convertInt64FromKeyValueTuple(
- mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumCounts");
+ mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumCounts",
+ tracker);
if (failed(numCounts))
return nullptr;
FailureOr<uint64_t> numFunctions = convertInt64FromKeyValueTuple(
- mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumFunctions");
+ mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumFunctions",
+ tracker);
if (failed(numFunctions))
return nullptr;
@@ -954,7 +1010,7 @@ convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
// Handle detailed summary.
FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
convertProfileSummaryDetailed(mlirModule, llvmModule,
- mdTuple->getOperand(summayIdx));
+ mdTuple->getOperand(summayIdx), tracker);
if (failed(detailed))
return nullptr;
@@ -967,15 +1023,14 @@ convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,
/// Invoke specific handlers for each known module flag value, returns nullptr
/// if the key is unknown or unimplemented.
-static Attribute
-convertModuleFlagValueFromMDTuple(ModuleOp mlirModule,
- const llvm::Module *llvmModule, StringRef key,
- llvm::MDTuple *mdTuple) {
+static Attribute convertModuleFlagValueFromMDTuple(
+ ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key,
+ llvm::MDTuple *mdTuple, llvm::ModuleSlotTracker &tracker) {
if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
return convertCGProfileModuleFlagValue(mlirModule, mdTuple);
if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
- return convertProfileSummaryModuleFlagValue(mlirModule, llvmModule,
- mdTuple);
+ return convertProfileSummaryModuleFlagValue(mlirModule, llvmModule, mdTuple,
+ tracker);
// Handle MDTuples whose operands are all MDStrings (e.g. "riscv-isa").
// Convert them to ArrayAttr of StringAttrs for a lossless round-trip.
Builder builder(mlirModule->getContext());
@@ -1003,13 +1058,14 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() {
valAttr = builder.getStringAttr(mdString->getString());
} else if (auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
valAttr = convertModuleFlagValueFromMDTuple(mlirModule, llvmModule.get(),
- key->getString(), mdTuple);
+ key->getString(), mdTuple,
+ getDiagSlotTracker());
}
if (!valAttr) {
emitWarning(mlirModule.getLoc())
<< "unsupported module flag value for key '" << key->getString()
- << "' : " << diagMD(val, llvmModule.get());
+ << "' : " << renderMetadata(val);
continue;
}
@@ -1168,13 +1224,13 @@ LogicalResult ModuleImport::convertGlobals() {
globalVar.getName() == getGlobalDtorsVarName()) {
if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
return emitError(UnknownLoc::get(context))
- << "unhandled global variable: " << ::diag(globalVar);
+ << "unhandled global variable: " << renderValue(globalVar);
}
continue;
}
if (failed(convertGlobal(&globalVar))) {
return emitError(UnknownLoc::get(context))
- << "unhandled global variable: " << ::diag(globalVar);
+ << "unhandled global variable: " << renderValue(globalVar);
}
}
return success();
@@ -1184,7 +1240,7 @@ LogicalResult ModuleImport::convertAliases() {
for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
if (failed(convertAlias(&alias))) {
return emitError(UnknownLoc::get(context))
- << "unhandled global alias: " << ::diag(alias);
+ << "unhandled global alias: " << renderValue(alias);
}
}
return success();
@@ -1194,7 +1250,7 @@ LogicalResult ModuleImport::convertIFuncs() {
for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
if (failed(convertIFunc(&ifunc))) {
return emitError(UnknownLoc::get(context))
- << "unhandled global ifunc: " << ::diag(ifunc);
+ << "unhandled global ifunc: " << renderValue(ifunc);
}
}
return success();
@@ -1254,9 +1310,8 @@ void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
if (failed(iface.setMetadataAttrs(builder, kind, node, op, *this))) {
if (emitExpensiveWarnings) {
Location loc = debugImporter->translateLoc(inst->getDebugLoc());
- emitWarning(loc) << "unhandled metadata: "
- << diagMD(node, llvmModule.get()) << " on "
- << ::diag(*inst);
+ emitWarning(loc) << "unhandled metadata: " << renderMetadata(node)
+ << " on " << renderValue(*inst);
}
}
}
@@ -1725,9 +1780,9 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
symbolRef =
getMetadataOperandSymbolRef(associatedMD->getOperand(0).get());
if (!symbolRef) {
- emitWarning(globalOp.getLoc()) << "unhandled associated metadata: "
- << diagMD(associatedMD, llvmModule.get())
- << " on " << ::diag(*globalVar);
+ emitWarning(globalOp.getLoc())
+ << "unhandled associated metadata: " << renderMetadata(associatedMD)
+ << " on " << renderValue(*globalVar);
} else {
globalOp.setAssociatedAttr(symbolRef);
}
@@ -2068,7 +2123,8 @@ FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
if (isa<llvm::GlobalValue>(constant))
error = " since global value is unsupported";
- return emitError(loc) << "unhandled constant: " << ::diag(*constant) << error;
+ return emitError(loc) << "unhandled constant: " << renderValue(*constant)
+ << error;
}
FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
@@ -2119,7 +2175,7 @@ FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
Attribute mdAttr = convertMetadataToAttr(md);
if (!mdAttr)
return emitError(mlirModule.getLoc())
- << "unsupported metadata: " << diagMD(md, llvmModule.get());
+ << "unsupported metadata: " << renderMetadata(md);
Value result =
MetadataAsValueOp::create(builder, UnknownLoc::get(context), mdAttr)
.getRes();
@@ -2134,7 +2190,7 @@ FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
Location loc = UnknownLoc::get(context);
if (auto *inst = dyn_cast<llvm::Instruction>(value))
loc = translateLoc(inst->getDebugLoc());
- return emitError(loc) << "unhandled value: " << ::diag(*value);
+ return emitError(loc) << "unhandled value: " << renderValue(*value);
}
FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) {
@@ -2440,7 +2496,7 @@ LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
return success();
Location loc = translateLoc(inst->getDebugLoc());
- return emitError(loc) << "unhandled intrinsic: " << ::diag(*inst);
+ return emitError(loc) << "unhandled intrinsic: " << renderValue(*inst);
}
ArrayAttr
@@ -2793,7 +2849,7 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
return success();
- return emitError(loc) << "unhandled instruction: " << ::diag(*inst);
+ return emitError(loc) << "unhandled instruction: " << renderValue(*inst);
}
LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
@@ -3425,8 +3481,8 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) {
if (!emitExpensiveWarnings)
return;
emitWarning(funcOp.getLoc())
- << "unhandled function metadata: "
- << diagMD(metadataNode, llvmModule.get()) << " on " << ::diag(*func);
+ << "unhandled function metadata: " << renderMetadata(metadataNode)
+ << " on " << renderValue(*func);
};
if (iface.isConvertibleMetadata(kind)) {
@@ -3572,7 +3628,8 @@ ModuleImport::processDebugOpArgumentsAndInsertionPt(
return {};
FailureOr<Value> argOperand = convertArgOperandToValue();
if (failed(argOperand)) {
- emitError(loc) << "failed to convert a debug operand: " << ::diag(*address);
+ emitError(loc) << "failed to convert a debug operand: "
+ << renderValue(*address);
return {};
}
@@ -3590,7 +3647,7 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
Location loc = translateLoc(dbgIntr->getDebugLoc());
auto emitUnsupportedWarning = [&]() {
if (emitExpensiveWarnings)
- emitWarning(loc) << "dropped intrinsic: " << ::diag(*dbgIntr);
+ emitWarning(loc) << "dropped intrinsic: " << renderValue(*dbgIntr);
return success();
};
@@ -3740,7 +3797,7 @@ LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
} else if (inst.getOpcode() != llvm::Instruction::PHI) {
if (emitExpensiveWarnings) {
Location loc = debugImporter->translateLoc(inst.getDebugLoc());
- emitWarning(loc) << "dropped instruction: " << ::diag(inst);
+ emitWarning(loc) << "dropped instruction: " << renderValue(inst);
}
}
}
@@ -3774,14 +3831,14 @@ ModuleImport::translateDereferenceableAttr(const llvm::MDNode *node,
// dereferenceable bytes.
if (node->getNumOperands() != 1)
return emitError(loc) << "dereferenceable metadata must have one operand: "
- << diagMD(node, llvmModule.get());
+ << renderMetadata(node);
auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
return emitError(loc) << "dereferenceable metadata operand must be a "
"non-negative constant integer: "
- << diagMD(node, llvmModule.get());
+ << renderMetadata(node);
bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
auto derefAttr = builder.getAttr<DereferenceableAttr>(
diff --git a/mlir/test/Target/LLVMIR/Import/function-metadata.ll b/mlir/test/Target/LLVMIR/Import/function-metadata.ll
index 2b244835d6a1dc..1c3825ef60b51e 100644
--- a/mlir/test/Target/LLVMIR/Import/function-metadata.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-metadata.ll
@@ -99,7 +99,7 @@ define void @ifunc_ref_metadata() !callees !0 {
; WARN: warning: unhandled function metadata:
; WARN-SAME: !{{[0-9]+}} = !{!"unknown", !"sample-pass"}
-; WARN-SAME: on define void @unknown_profile_metadata()
+; WARN-SAME: on @unknown_profile_metadata
; CHECK-LABEL: llvm.func @unknown_profile_metadata()
; CHECK-NOT: function_metadata
; CHECK: llvm.return
@@ -113,7 +113,7 @@ define void @unknown_profile_metadata() !prof !0 {
; WARN: warning: unhandled function metadata:
; WARN-SAME: !{{[0-9]+}} = distinct !{!"identity"}
-; WARN-SAME: on define void @distinct_metadata()
+; WARN-SAME: on @distinct_metadata
; CHECK-LABEL: llvm.func @distinct_metadata()
; CHECK-NOT: function_metadata
; CHECK: llvm.return
diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll
index d57c92db7253bd..a1775238ccf09c 100644
--- a/mlir/test/Target/LLVMIR/Import/global-variables.ll
+++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll
@@ -455,3 +455,10 @@ define ptr @associated_ifunc_resolver() {
@a = external global i8, !absolute_symbol !0
!0 = !{i64 -1, i64 -1}
+
+; // -----
+
+; Globals render by name only: a large initializer must not be embedded.
+; WARN: warning: unhandled associated metadata: {{.*}} on @big{{ *}}{{$}}
+ at big = global [300 x i8] c"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", !associated !0
+!0 = !{ptr null}
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 91f558ebf4f08c..fbf0ccba0f5ce8 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -610,3 +610,37 @@ define void @disable_tail_calls_invalid() #0 {
}
attributes #0 = { "disable-tail-calls"="invalid" }
+
+; // -----
+
+; A diagnostic rendering past the bound is truncated, not embedded whole.
+; CHECK: error: unsupported TBAA node format: !{{[0-9]+}} = !{!{{[0-9]+}}, i64 1, !"aaa
+; CHECK-SAME: {{a+[.][.][.]}} <truncated>{{$}}
+define dso_local void @tbaa_truncated(ptr %0) {
+ store i32 1, ptr %0, align 4, !tbaa !2
+ ret void
+}
+
+!2 = !{!3, !3, i64 0, i64 4}
+!3 = !{!4, i64 4, !"int"}
+!4 = !{!5, i64 1, !"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
+!5 = !{!"Simple C++ TBAA"}
+
+; // -----
+
+; Two functions warn in one import; each diagnostic numbers its own
+; function's locals, so sharing the slot tracker must not leak numbering
+; across functions.
+; CHECK: warning: unhandled metadata: ![[ID0:[0-9]+]] = distinct !{![[ID0]], i32 42} on {{.*}}%1 = load i32, ptr %p
+; CHECK: warning: unhandled metadata: ![[ID1:[0-9]+]] = distinct !{![[ID1]], i32 43} on {{.*}}%1 = load i64, ptr %q
+define void @reuse_a(ptr %p) {
+ %1 = load i32, ptr %p, !llvm.loop !0
+ ret void
+}
+define void @reuse_b(ptr %q) {
+ %1 = load i64, ptr %q, !llvm.loop !1
+ ret void
+}
+
+!0 = distinct !{!0, i32 42}
+!1 = distinct !{!1, i32 43}
More information about the Mlir-commits
mailing list