StableHLO Compatibility

StableHLO is a backward compatible ML compute opset inspired by HLO/MHLO. This document explains the kind and the extent of the compatibility guarantees that StableHLO provides, based on the process established in the compatibility RFC.

Versions

The current version of StableHLO can be found in Version.h.

In the 0.x.x series, StableHLO is providing limited compatibility guarantees as described in the Guarantees section. In H2 2023, we are planning to release StableHLO 1.0.0, which will provide full compatibility guarantees - see the Future work section for more details.

The minor version is bumped every time changes to the StableHLO opset are made, and the patch version is bumped every time we integrate StableHLO downstream, i.e. into the openxla/xla repository.

Guarantees

6 months of backward compatibility: Portable artifacts serialized by an old version of libStablehlo have the same semantics* when deserialized by a new version of libStablehlo if these versions are built from openxla/stablehlo commits which are less than 6 months apart.

1 month of forward compatibility: Portable artifacts serialized by a new version of libStablehlo have the same semantics* when deserialized by an old version of libStablehlo if these versions are built from openxla/stablehlo commits which are less than 1 month apart, unless the program is using new features introduced since the old version.

* StableHLO programs are converted to/from portable artifacts via compatibility APIs, and the semantics of these programs are defined by the StableHLO spec. In the future, we will provide a reference implementation which will provide an executable version of the specification.

APIs

Portable artifacts can be created using either the stablehlo-translate tool, or directly in C++ or Python APIs. Serialization needs a target version of StableHLO to write an artifact written in #.#.# format (See Version.h for current version). Deserialization uses the current version of StableHLO to read an artifact.

stablehlo-translate

This is the easiest way to create and read a portable artifact.

# Write a StableHLO program to a portable artifact
$ stablehlo-translate --serialize file.mlir --target=0.9.0 > portable_artifact.mlir.bc

# Read StableHLO portable artifact
$ stablehlo-translate --deserialize portable_artifact.mlir.bc

C++

For programmatic workflows, StableHLO provides the following compatibility APIs:

// From: #include "stablehlo/api/PortableApi.h"

// Get the current StableHLO version.
//
// This value can be used as the `targetVersion` argument to
// `serializePortableArtifact`.
std::string getCurrentVersion();

// Get the minimum supported StableHLO version.
//
// This value can be used as the `targetVersion` argument to
// `serializePortableArtifact`.
std::string getMinimumVersion();

// From: #include "stablehlo/dialect/Serialization.h"

// Write a StableHLO program to a portable artifact
// Writes a stable payload for `module` to `os`. If compatibility with a
// previous version of StableHLO is required, provide the required version
// string `#.#.#` for `targetVersion`.
//
// Can fail if `module` cannot be expressed in the `targetVersion` version of
// StableHLO, e.g. if it's using new or removed features, or if it involves
// unsupported dialects.
LogicalResult serializePortableArtifact(ModuleOp module,
                                        StringRef targetVersion,
                                        raw_ostream& os);

// Read StableHLO portable artifact
//
// Can fail if `sourceStr` cannot be expressed in the current version of
// StableHLO, e.g. if it's using incompatible features. Returns nullptr if
// `sourceStr` is invalid or fails to deserialize.
OwningOpRef<ModuleOp> deserializePortableArtifact(StringRef sourceStr,
                                                  MLIRContext* context);

See stablehlo/api/PortableApi.h and stablehlo/dialect/Serialization.h for full APIs.

See StablehloTranslateMain.cpp for example usage of these APIs.

Python

StableHLO also provides Python bindings to the C++ compatibility APIs:

def get_current_version() -> str: ...
def get_minimum_version() -> str: ...
def serialize_portable_artifact(module: ir.Module, target_version: str) -> bytes: ...
def serialize_portable_artifact(module: str, target_version: str) -> bytes: ...
def deserialize_portable_artifact(context: ir.Context, artifact: bytes) -> ir.Module: ...
def deserialize_portable_artifact(artifact: bytes) -> str: ...

See StablehloModule.cpp for full Python APIs.

See stablehlo.py > test_serialization_apis for roundtrip examples of using the Python Serialization APIs.

Tests

We have a compatibility suite in stablehlo/testdata that consists of several thousand files dumped from JAX tests. For every pull request, we are testing that deserialization of the compatibility suite at HEAD produces StableHLO programs which are syntactically identical to the original StableHLO programs that were serialized by the latest release of libStablehlo.

Future work

5 years of compatibility guarantees. In H2 2023, we are planning to release StableHLO v1.0 which will implement high-priority improvements, including cleaning up the frontend contract and providing a reference implementation. Having obtained these improvements and resolved key specification compliance issues, StableHLO will be ready for full compatibility guarantees - 5 years of forward and backward compatibility. See roadmap.md for details.

Organize compatibility suite. At the moment, the compatibility suite is one directory with many unstructured files. We are planning to triage and organize it, making sure that it's organized, comprehensive and deduplicated (#1240).

Use reference implementation. At the moment, compatibility testing consists of deserializing the compatibility suite serialized by older versions of libStablehlo and making sure that deserialization produces syntactically identical programs. We are planning to also use a reference implementation in these tests, relaxing the overly onerous requirement of syntactical identity and comprehensively testing the reference implementation (#1245).

Out of scope

Source compatibility for C, C++ and Python APIs within libStablehlo is an aspirational goal. At the moment, we don't offer source compatibility guarantees, but please let us know if this is an important use case for you, and we can have a discussion about supporting it (#1247).