Skip to content

[mlir][bytecode] Fix D155919 and enable backward-compatibility and back-deployment between version 5 and version 6 of the bytecode encoding #70498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 81 additions & 24 deletions mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,36 @@ static const char *const valueRangeReturnCode = R"(
)";

/// Read operand/result segment_size from bytecode.
static const char *const readBytecodeSegmentSize = R"(
if ($_reader.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6) {
::mlir::DenseI32ArrayAttr attr;
if (::mlir::failed($_reader.readAttribute(attr))) return ::mlir::failure();
if (attr.size() > static_cast<int64_t>(sizeof($_storage) / sizeof(int32_t))) {
$_reader.emitError("size mismatch for operand/result_segment_size");
return ::mlir::failure();
static const char *const readBytecodeSegmentSizeNative = R"(
if ($_reader.getBytecodeVersion() >= /*kNativePropertiesODSSegmentSize=*/6)
return $_reader.readSparseArray(::llvm::MutableArrayRef($_storage));
)";

static const char *const readBytecodeSegmentSizeLegacy = R"(
if ($_reader.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6) {
auto &$_storage = prop.$_propName;
::mlir::DenseI32ArrayAttr attr;
if (::mlir::failed($_reader.readAttribute(attr))) return ::mlir::failure();
if (attr.size() > static_cast<int64_t>(sizeof($_storage) / sizeof(int32_t))) {
$_reader.emitError("size mismatch for operand/result_segment_size");
return ::mlir::failure();
}
::llvm::copy(::llvm::ArrayRef<int32_t>(attr), $_storage.begin());
}
::llvm::copy(::llvm::ArrayRef<int32_t>(attr), $_storage.begin());
} else {
return $_reader.readSparseArray(::llvm::MutableArrayRef($_storage));
}
)";

/// Write operand/result segment_size to bytecode.
static const char *const writeBytecodeSegmentSize = R"(
if ($_writer.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6)
$_writer.writeAttribute(::mlir::DenseI32ArrayAttr::get(getContext(), $_storage));
else
$_writer.writeSparseArray(::llvm::ArrayRef($_storage));
static const char *const writeBytecodeSegmentSizeNative = R"(
if ($_writer.getBytecodeVersion() >= /*kNativePropertiesODSSegmentSize=*/6)
$_writer.writeSparseArray(::llvm::ArrayRef($_storage));
)";

/// Write operand/result segment_size to bytecode.
static const char *const writeBytecodeSegmentSizeLegacy = R"(
if ($_writer.getBytecodeVersion() < /*kNativePropertiesODSSegmentSize=*/6) {
auto &$_storage = prop.$_propName;
$_writer.writeAttribute(::mlir::DenseI32ArrayAttr::get($_ctxt, $_storage));
}
)";

/// A header for indicating code sections.
Expand Down Expand Up @@ -389,6 +399,14 @@ class OpOrAdaptorHelper {
return resultSegmentsSize;
}

uint32_t getOperandSegmentSizesLegacyIndex() {
return operandSegmentSizesLegacyIndex;
}

uint32_t getResultSegmentSizesLegacyIndex() {
return resultSegmentSizesLegacyIndex;
}

private:
// Compute the attribute metadata.
void computeAttrMetadata();
Expand All @@ -407,6 +425,12 @@ class OpOrAdaptorHelper {
std::optional<NamedProperty> resultSegmentsSize;
std::string resultSegmentsSizeStorage;

// Indices to store the position in the emission order of the operand/result
// segment sizes attribute if emitted as part of the properties for legacy
// bytecode encodings, i.e. versions less than 6.
uint32_t operandSegmentSizesLegacyIndex = 0;
uint32_t resultSegmentSizesLegacyIndex = 0;

// The number of required attributes.
unsigned numRequired;
};
Expand Down Expand Up @@ -435,8 +459,8 @@ void OpOrAdaptorHelper::computeAttrMetadata() {
"::mlir::DenseI32ArrayAttr::get($_ctxt, $_storage)",
/*convertFromAttributeCall=*/
"return convertFromAttribute($_storage, $_attr, $_diag);",
/*readFromMlirBytecodeCall=*/readBytecodeSegmentSize,
/*writeToMlirBytecodeCall=*/writeBytecodeSegmentSize,
/*readFromMlirBytecodeCall=*/readBytecodeSegmentSizeNative,
/*writeToMlirBytecodeCall=*/writeBytecodeSegmentSizeNative,
/*hashPropertyCall=*/
"::llvm::hash_combine_range(std::begin($_storage), "
"std::end($_storage));",
Expand Down Expand Up @@ -478,6 +502,21 @@ void OpOrAdaptorHelper::computeAttrMetadata() {
return lhs.attrName < rhs.attrName;
});

// Store the position of the legacy operand_segment_sizes /
// result_segment_sizes so we can emit a backward compatible property readers
// and writers.
StringRef legacyOperandSegmentSizeName =
StringLiteral("operand_segment_sizes");
StringRef legacyResultSegmentSizeName = StringLiteral("result_segment_sizes");
operandSegmentSizesLegacyIndex = 0;
resultSegmentSizesLegacyIndex = 0;
for (auto item : sortedAttrMetadata) {
if (item.attrName < legacyOperandSegmentSizeName)
++operandSegmentSizesLegacyIndex;
if (item.attrName < legacyResultSegmentSizeName)
++resultSegmentSizesLegacyIndex;
}

// Compute the subrange bounds for each attribute.
numRequired = 0;
for (AttributeMetadata &attr : sortedAttrMetadata) {
Expand Down Expand Up @@ -1580,15 +1619,33 @@ void OpEmitter::genPropertiesSupportForBytecode(
readPropertiesMethod
<< " auto &prop = state.getOrAddProperties<Properties>(); (void)prop;";
writePropertiesMethod << " auto &prop = getProperties(); (void)prop;\n";
for (const auto &attrOrProp : attrOrProperties) {
for (const auto &item : llvm::enumerate(attrOrProperties)) {
auto &attrOrProp = item.value();
FmtContext fctx;
fctx.addSubst("_reader", "reader")
.addSubst("_writer", "writer")
.addSubst("_storage", propertyStorage)
.addSubst("_ctxt", "this->getContext()");
// If the op emits operand/result segment sizes as a property, emit the
// legacy reader/writer in the appropriate order to allow backward
// compatibility and back deployment.
if (emitHelper.getOperandSegmentsSize().has_value() &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment for the block around the legacy stuff

item.index() == emitHelper.getOperandSegmentSizesLegacyIndex()) {
FmtContext fmtCtxt(fctx);
fmtCtxt.addSubst("_propName", operandSegmentAttrName);
readPropertiesMethod << tgfmt(readBytecodeSegmentSizeLegacy, &fmtCtxt);
writePropertiesMethod << tgfmt(writeBytecodeSegmentSizeLegacy, &fmtCtxt);
}
if (emitHelper.getResultSegmentsSize().has_value() &&
item.index() == emitHelper.getResultSegmentSizesLegacyIndex()) {
FmtContext fmtCtxt(fctx);
fmtCtxt.addSubst("_propName", resultSegmentAttrName);
readPropertiesMethod << tgfmt(readBytecodeSegmentSizeLegacy, &fmtCtxt);
writePropertiesMethod << tgfmt(writeBytecodeSegmentSizeLegacy, &fmtCtxt);
}
if (const auto *namedProperty =
attrOrProp.dyn_cast<const NamedProperty *>()) {
StringRef name = namedProperty->name;
FmtContext fctx;
fctx.addSubst("_reader", "reader")
.addSubst("_writer", "writer")
.addSubst("_storage", propertyStorage)
.addSubst("_ctxt", "this->getContext()");
readPropertiesMethod << formatv(
R"(
{{
Expand Down