[Mlir-commits] [mlir] [mlir][Printer] Honor --mlir-elide-resource-strings-if-larger when serializing of large blobs (PR #217579)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Aug 20 03:30:27 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-core
Author: Natanael Cintean (natanael-cintean)
<details>
<summary>Changes</summary>
Bringing in changes merged in main [PR 213920](https://github.com/llvm/llvm-project/pull/213920)
OperationPrinter::printResourceFileMetadata elides resource entries larger than --mlir-elide-resource-strings-if-larger (charLimit), but always materializes the full serialized string first (e.g. hex-encoding the entire blob) and only checks the length afterward, discarding the string if it's too long. For large dialect/external resource blobs, this wastes significant time and memory hex-encoding data that is guaranteed to be elided.
The time and memory consumption is especially noticeable when printing the IR for a large number of passes.
Extend ResourceBuilder::PrintFn to accept an additional sizeHint — the exact number of characters the value will serialize to when known ahead of time (currently computed for buildBlob's hex-encoded output; -1 for buildBool/buildString where it's cheap to compute directly).
printResourceFileMetadata then skips calling the serialization callback entirely when sizeHint already exceeds charLimit, avoiding the wasted encoding work while preserving identical printed output.
---
Full diff: https://github.com/llvm/llvm-project/pull/217579.diff
2 Files Affected:
- (modified) mlir/lib/IR/AsmPrinter.cpp (+38-16)
- (modified) mlir/test/IR/pretty-resources-print.mlir (+53-1)
``````````diff
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index b95ab00bd5fdd..248d2943b9514 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -3467,33 +3467,49 @@ class OperationPrinter : public AsmPrinter::Impl, private OpAsmPrinter {
class ResourceBuilder : public AsmResourceBuilder {
public:
using ValueFn = function_ref<void(raw_ostream &)>;
- using PrintFn = function_ref<void(StringRef, ValueFn)>;
+ // `sizeHint` is the exact number of characters `valueFn` will write, or -1
+ // if unknown, so the char limit can be applied before paying the cost of
+ // invoking `valueFn` (e.g. hex-encoding a large blob).
+ using PrintFn = function_ref<void(StringRef, ValueFn, int64_t sizeHint)>;
ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
~ResourceBuilder() override = default;
void buildBool(StringRef key, bool data) final {
- printFn(key, [&](raw_ostream &os) { os << (data ? "true" : "false"); });
+ printFn(
+ key, [&](raw_ostream &os) { os << (data ? "true" : "false"); },
+ /*sizeHint=*/-1);
}
void buildString(StringRef key, StringRef data) final {
- printFn(key, [&](raw_ostream &os) {
- os << "\"";
- llvm::printEscapedString(data, os);
- os << "\"";
- });
+ printFn(
+ key,
+ [&](raw_ostream &os) {
+ os << "\"";
+ llvm::printEscapedString(data, os);
+ os << "\"";
+ },
+ /*sizeHint=*/-1);
}
void buildBlob(StringRef key, ArrayRef<char> data,
uint32_t dataAlignment) final {
- printFn(key, [&](raw_ostream &os) {
- // Store the blob in a hex string containing the alignment and the data.
- llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
- os << "\"0x"
- << llvm::toHex(StringRef(reinterpret_cast<char *>(&dataAlignmentLE),
- sizeof(dataAlignment)))
- << llvm::toHex(StringRef(data.data(), data.size())) << "\"";
- });
+ // Two hex chars per byte of the alignment word and the data, plus the
+ // `"0x`/`"` wrapping; exact, so the limit can be checked pre-encoding.
+ int64_t sizeHint = 2 * int64_t(sizeof(dataAlignment) + data.size()) + 4;
+ printFn(
+ key,
+ [&](raw_ostream &os) {
+ // Store the blob in a hex string containing the alignment and the
+ // data.
+ llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
+ os << "\"0x"
+ << llvm::toHex(
+ StringRef(reinterpret_cast<char *>(&dataAlignmentLE),
+ sizeof(dataAlignment)))
+ << llvm::toHex(StringRef(data.data(), data.size())) << "\"";
+ },
+ sizeHint);
}
private:
@@ -3558,7 +3574,8 @@ void OperationPrinter::printResourceFileMetadata(
auto processProvider = [&](StringRef dictName, StringRef name, auto &provider,
auto &&...providerArgs) {
bool hadEntry = false;
- auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn) {
+ auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn,
+ int64_t sizeHint) {
checkAddMetadataDict();
std::string resourceStr;
@@ -3570,6 +3587,11 @@ void OperationPrinter::printResourceFileMetadata(
if (charLimit.value() == 0)
return;
+ // Skip serializing entirely if the exact size already exceeds the
+ // limit, e.g. hex-encoding a large blob.
+ if (sizeHint >= 0 && uint64_t(sizeHint) > charLimit.value())
+ return;
+
llvm::raw_string_ostream ss(resourceStr);
valueFn(ss);
diff --git a/mlir/test/IR/pretty-resources-print.mlir b/mlir/test/IR/pretty-resources-print.mlir
index 980af80343d47..a2733d13cebe8 100644
--- a/mlir/test/IR/pretty-resources-print.mlir
+++ b/mlir/test/IR/pretty-resources-print.mlir
@@ -4,17 +4,36 @@
// RUN: mlir-opt %s --mlir-elide-resource-strings-if-larger=0| FileCheck %s --check-prefix=ZERO
+// blob3's exact serialized size (quotes + "0x" + hex(alignment) + hex(data)) is 14 chars;
+// these two RUN lines check the off-by-one boundary of the sizeHint-based elision.
+// RUN: mlir-opt %s --mlir-elide-resource-strings-if-larger=14| FileCheck %s --check-prefix=BOUND14
+// RUN: mlir-opt %s --mlir-elide-resource-strings-if-larger=13| FileCheck %s --check-prefix=BOUND13
// To ensure we print the resource keys, have reference to them
// CHECK: attr = dense_resource<blob1> : tensor<3xi64>
// ZERO: attr = dense_resource<blob1> : tensor<3xi64>
+// BOUND14: attr = dense_resource<blob1> : tensor<3xi64>
+// BOUND13: attr = dense_resource<blob1> : tensor<3xi64>
"test.blob1op"() {attr = dense_resource<blob1> : tensor<3xi64> } : () -> ()
// CHECK-NEXT: attr = dense_resource<blob2> : tensor<3xi64>
// ZERO-NEXT: attr = dense_resource<blob2> : tensor<3xi64>
+// BOUND14-NEXT: attr = dense_resource<blob2> : tensor<3xi64>
+// BOUND13-NEXT: attr = dense_resource<blob2> : tensor<3xi64>
"test.blob2op"() {attr = dense_resource<blob2> : tensor<3xi64> } : () -> ()
+// CHECK-NEXT: attr = dense_resource<blob3> : tensor<1xi8>
+// ZERO-NEXT: attr = dense_resource<blob3> : tensor<1xi8>
+// BOUND14-NEXT: attr = dense_resource<blob3> : tensor<1xi8>
+// BOUND13-NEXT: attr = dense_resource<blob3> : tensor<1xi8>
+"test.blob3op"() {attr = dense_resource<blob3> : tensor<1xi8> } : () -> ()
+
// CHECK: {-#
+// CHECK-NEXT: dialect_resources: {
+// CHECK-NEXT: builtin: {
+// CHECK-NEXT: blob3: "0x0800000001"
+// CHECK-NEXT: }
+// CHECK-NEXT: },
// CHECK-NEXT: external_resources: {
// CHECK-NEXT: external: {
// CHECK-NEXT: "backslash\\tab\09": true,
@@ -31,11 +50,44 @@
// ZERO-EMPTY:
// ZERO-NEXT: #-}
+// At the exact boundary (limit == blob3's exact size) blob3 must still be printed,
+// since the sizeHint fast-path only elides when size is strictly greater than the limit.
+// BOUND14: {-#
+// BOUND14-NEXT: dialect_resources: {
+// BOUND14-NEXT: builtin: {
+// BOUND14-NEXT: blob3: "0x0800000001"
+// BOUND14-NEXT: }
+// BOUND14-NEXT: },
+// BOUND14-NEXT: external_resources: {
+// BOUND14-NEXT: external: {
+// BOUND14-NEXT: "backslash\\tab\09": true,
+// BOUND14-NEXT: string: "\22string\22"
+// BOUND14-NEXT: },
+// BOUND14-NEXT: other_stuff: {
+// BOUND14-NEXT: bool: true
+// BOUND14-NEXT: }
+// BOUND14-NEXT: }
+// BOUND14-NEXT: #-}
+
+// One below the boundary, blob3 is elided and no dialect_resources dict is emitted.
+// Note: the escaped `string` entry is also exactly 14 chars, so it is elided here too.
+// BOUND13: {-#
+// BOUND13-NEXT: external_resources: {
+// BOUND13-NEXT: external: {
+// BOUND13-NEXT: "backslash\\tab\09": true
+// BOUND13-NEXT: },
+// BOUND13-NEXT: other_stuff: {
+// BOUND13-NEXT: bool: true
+// BOUND13-NEXT: }
+// BOUND13-NEXT: }
+// BOUND13-NEXT: #-}
+
{-#
dialect_resources: {
builtin: {
blob1: "0x08000000010000000000000002000000000000000300000000000000",
- blob2: "0x08000000040000000000000005000000000000000600000000000000"
+ blob2: "0x08000000040000000000000005000000000000000600000000000000",
+ blob3: "0x0800000001"
}
},
external_resources: {
``````````
</details>
https://github.com/llvm/llvm-project/pull/217579
More information about the Mlir-commits
mailing list