Skip to content

[SYCL] Support --offload-compress in clang-linker-wrapper#22605

Open
bviyer wants to merge 21 commits into
syclfrom
bviyer-sycl-compress-support
Open

[SYCL] Support --offload-compress in clang-linker-wrapper#22605
bviyer wants to merge 21 commits into
syclfrom
bviyer-sycl-compress-support

Conversation

@bviyer

@bviyer bviyer commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Forward --offload-compress (and --offload-compression-level=) from the driver to clang-linker-wrapper under the new offloading driver. In wrapSYCLBinariesFromFile, zstd-compress each SYCL device image whose payload is at or above --offload-compression-threshold= (default 512 bytes) and tag it with the new BIF_Compressed image format so the SYCL runtime decompresses lazily via CompressedRTDeviceBinaryImage.

Significant help from Claude Opus 4.7.

@bviyer
bviyer requested review from YuriPlyakhin and maksimsab July 12, 2026 15:23
@bviyer
bviyer marked this pull request as ready for review July 14, 2026 14:05
@bviyer
bviyer requested review from a team as code owners July 14, 2026 14:05
// The --compress flag above is a different mechanism: for HIP only, it is
// forwarded verbatim to a clang-offload-bundler subprocess which does the
// compression itself.
def offload_compress : Flag<["--"], "offload-compress">,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of adding new flags could we just re-use the existing ones? Then I don't think we need any driver changes, it seems addOffloadCompressArgs should do what we need if we make clang-linker-wrapper do the right thing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. I made it use --compress and --compress-level=

BIF_Native, // Native Image kind
BIF_SPIRV, // SPIR-V
BIF_LLVMBC, // LLVM bitcode
BIF_CompressedNone // zstd-compressed image; format-of-original unknown

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe we could just call it BIF_Compressed unless we need different BIFCompressed versions for different original formats, which it seems like we don't

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

case SYCLBinaryImageFormat::BIF_LLVMBC:
return 3;
case SYCLBinaryImageFormat::BIF_CompressedNone:
return 4;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I assume the SYCL runtime already knows how to handle this and the format matches the old offload model?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes.

"'--offload-compress' is specified but zstd is not available");

int Level = 10; // default zstd level, matches clang-offload-wrapper
int Threshold = 512; // skip compression below this many bytes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if we can h ave a shared function that both clang-offload-wrapper and clang-linker-wrapper use until we remove old offload model support. Maybe we could put it in llvm/lib/Frontend/Offloading/Utility.cpp?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is fixed here ec31530. Its a bit messy.

@bviyer
bviyer requested a review from bader as a code owner July 15, 2026 23:27
@bviyer
bviyer force-pushed the bviyer-sycl-compress-support branch from 2361b30 to ec31530 Compare July 15, 2026 23:30
@bviyer
bviyer requested a review from sarnex July 15, 2026 23:32
@bader

bader commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@bviyer, please, remove .gdbinit from PR.

@bviyer

bviyer commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@bviyer, please, remove .gdbinit from PR.

Sorry. Fixed.

@bader
bader removed their request for review July 15, 2026 23:52

@sarnex sarnex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice cleanup! some comments below

// CHECK-NO-COMPRESS-NOT: {{.*}}clang-linker-wrapper{{.*}}"--compress"

// --no-offload-compress overrides an earlier --offload-compress.
// RUN: %clangxx -### -fsycl --offload-new-driver --offload-compress \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should we check the opposite case, where we have --no-offload-compress --offload-compress

// consume them here and zstd-compress each image payload in place, flipping
// its Format to BIF_Compressed. The SYCL runtime recognizes that tag and
// decompresses lazily via CompressedRTDeviceBinaryImage.
if (Args.hasArg(OPT_compress)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could we move this all into a separate function like compressSYCLImages or something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

// Forward-declared instead of #include "llvm/Frontend/Offloading/Utility.h"
// because pulling in that header (transitively llvm/Object/OffloadBinary.h)
// makes llvm::object::OffloadKind visible via `using namespace llvm::object`
// above, which collides with the local anonymous-namespace `enum OffloadKind`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IMO instead of this workaround we should fix the local anonymous namespace issue, maybe rename it to something that shows how it's different from the OffloadBinary.h one if really we need a separate enum

@bviyer bviyer Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed to OffloadModelKind (didn't want to remove the kind since it was used in several places and looks like it means something).

// pre-refactor behavior which errored regardless of image kind or
// format. The guarded branch below would otherwise skip the check for
// non-SYCL / explicit-format images.
if (OffloadCompressDevImgs && !llvm::compression::zstd::isAvailable())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IMO changing the error behavior is fine, if we don't actually try to compress anything it's fine to not error, having this extra check is confusing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.


for (auto &Image : Images) {
SmallVector<uint8_t, 0> CompressedBytes;
Expected<bool> Compressed = offloading::compressSYCLDeviceImage(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we make it a bit clearer on what the return type is with something like

Expected<bool> DidCompressOrErr = ...
if (!DidCompressOrErr)
        return DidCompressOrErr.takeError();
bool DidCompres = *DidCompressOrErr;
/// use DidCompress

At first it was unclear to me what the bool represented so I think making it explicit would help readability

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. However, I didn't create a new variable called DidCompress I just used the check on (*DidCompressOrErr). Generally, I do not create new variables unless the item is used in multiple places.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i think we lost the LLVM_ENABLE_EXCEPTIONS handling which we probably need

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@sarnex sarnex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

did you forget to push your changes to the PR? i'm not seeing any new commits with fixes

@bviyer
bviyer requested a review from sarnex July 16, 2026 19:16

@sarnex sarnex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm thanks! just some final nits

/// clang-offload-wrapper also uses; the surrounding loop isn't shared
/// because that tool operates on one image at a time and emits an LLVM
/// Constant directly, not a SYCLImage list.
static Error compressSYCLImages(SmallVectorImpl<offloading::SYCLImage> &Images,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sorry instead can we put this in the namespace sycl starting at line ~515 and call it compressImages? Thanks

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

/// tagging its Format as BIF_Compressed. --compress and --compression-level=
/// are the same flags HIP forwards to clang-offload-bundler; for SYCL we
/// consume them here. The per-image work delegates to
/// offloading::compressSYCLDeviceImage, which the old-driver

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

im not sure we need to mention the old offloading model here or anywhere in code comments in new offload model code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

// enum.
enum OffloadKind {
// enum. Distinct from llvm::object::OffloadKind (in Object/OffloadBinary.h),
// which is the 16-bit bitmask on the OffloadBinary wire format

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

im not sure what wire format means

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep, it was an artifact of something I was typing. I reworded to "...in the OffloadBinary header."

// command-line-parsed tag with an extra Host slot and First/Last sentinels,
// serialized as a uint8_t into the SYCL runtime's sycl_device_binary_struct
// Kind field.
enum OffloadModelKind {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe OldOffloadKind?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

bviyer added 9 commits July 16, 2026 14:36
Forward --offload-compress (and --offload-compression-level=) from the
driver to clang-linker-wrapper under the new offloading driver. In
wrapSYCLBinariesFromFile, zstd-compress each SYCL device image whose
payload is at or above --offload-compression-threshold= (default 512
bytes) and tag it with the new BIF_CompressedNone image format so the
SYCL runtime decompresses lazily via CompressedRTDeviceBinaryImage.
ClangOffLoadWrappper and ClangLinkerWrapper.
@bviyer
bviyer force-pushed the bviyer-sycl-compress-support branch from e45280d to e79b396 Compare July 16, 2026 22:19
Comment thread llvm/include/llvm/Frontend/Offloading/Utility.h Outdated

@YuriPlyakhin YuriPlyakhin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please update PR description: BIF_CompressedNone -> BIF_Compressed

@YuriPlyakhin YuriPlyakhin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please add a functional test for the new compression path to test changes in clang-linker-wrapper.cpp?
Test would run clang-linker-wrapper --compress and would verify the emitted image is tagged with BIF_Compressed.
Also it would check invalid value for --offload-compression-level= error message.
FYI: The old wrapper is tested by clang-offload-wrapper-zstd.c

Co-authored-by: Yury Plyakhin <yury.plyakhin@intel.com>
@bviyer

bviyer commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Please update PR description: BIF_CompressedNone -> BIF_Compressed

Fixed.

@bviyer

bviyer commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Could you please add a functional test for the new compression path to test changes in clang-linker-wrapper.cpp? Test would run clang-linker-wrapper --compress and would verify the emitted image is tagged with BIF_Compressed. Also it would check invalid value for --offload-compression-level= error message. FYI: The old wrapper is tested by clang-offload-wrapper-zstd.c

Added test here: 48bf119

@bviyer
bviyer requested a review from YuriPlyakhin July 17, 2026 17:56

// RUN: %clang -cc1 -fsycl-is-device -disable-llvm-passes -triple=spir64-unknown-unknown %s -emit-llvm-bc -o %t.device.bc
// RUN: llvm-offload-binary -o %t.fat --image=file=%t.device.bc,kind=sycl,triple=spir64-unknown-unknown
// RUN: %clang -cc1 %s -triple=x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.fat

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i think we also need x86-registered-target in REQUIRES

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Comment on lines +28 to +29
// CHECK-COMPRESS: [Compression] Original image size:
// CHECK-COMPRESS: [Compression] Compressed image size:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i think we should be able to do basic math operations in Filecheck https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-numeric-substitution-blocks

could we at least verify the compressed size is smaller than the original?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@bviyer
bviyer requested a review from sarnex July 17, 2026 19:59

@sarnex sarnex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks!

@sys-ce-bb

Copy link
Copy Markdown
Contributor

@intel/llvm-gatekeepers please consider merging

Comment thread clang/test/Driver/clang-linker-wrapper-zstd.cpp Outdated
Comment thread clang/test/Driver/clang-linker-wrapper-zstd.cpp Outdated
Comment thread clang/test/Driver/clang-linker-wrapper-zstd.cpp Outdated

@YuriPlyakhin YuriPlyakhin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM. Few nits - all related to too verbose comments. Feel free to ignore. Thanks! :)

bviyer and others added 2 commits July 20, 2026 13:00
Co-authored-by: Yury Plyakhin <yury.plyakhin@intel.com>
Co-authored-by: Yury Plyakhin <yury.plyakhin@intel.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds SYCL device-image compression support to the new offloading driver path by forwarding --offload-compress (and --offload-compression-level=) to clang-linker-wrapper, then zstd-compressing SYCL images in wrapSYCLBinariesFromFile and tagging them as BIF_Compressed so the SYCL runtime can lazily decompress them.

Changes:

  • Introduces offloading::compressSYCLDeviceImage() as a shared helper for zstd compression with threshold/verbosity support.
  • Extends SYCL wrapper image-format handling with a new SYCLBinaryImageFormat::BIF_Compressed (mapped to int8 value 4).
  • Adds clang-linker-wrapper in-place compression of SYCL device images when --compress is present, plus new driver and wrapper tests.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
llvm/lib/Frontend/Offloading/Utility.cpp Implements compressSYCLDeviceImage() using LLVM zstd support and verbose size reporting.
llvm/include/llvm/Frontend/Offloading/Utility.h Declares compressSYCLDeviceImage() API and documents parameters/defaults.
llvm/lib/Frontend/Offloading/SYCLOffloadWrapper.cpp Maps new BIF_Compressed to serialized int8 format value.
llvm/include/llvm/Frontend/Offloading/SYCLOffloadWrapper.h Adds BIF_Compressed to the SYCL image-format enum.
clang/tools/clang-offload-wrapper/CMakeLists.txt Links clang-offload-wrapper against FrontendOffloading to use the shared helper.
clang/tools/clang-offload-wrapper/ClangOffloadWrapper.cpp Switches compression logic to call the shared helper; renames kind enum to OldOffloadKind.
clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp Adds --compress path that compresses SYCL images and tags them BIF_Compressed.
clang/test/Driver/sycl-offload-new-driver-compression.cpp Verifies driver forwarding of compression flags to clang-linker-wrapper.
clang/test/Driver/clang-linker-wrapper-zstd.cpp End-to-end wrapper test: compression happens, format tagged, level parsing and diagnostics.

Comment thread llvm/lib/Frontend/Offloading/Utility.cpp Outdated
Comment on lines +1119 to +1123
if (auto *A = Args.getLastArg(OPT_compression_level_eq))
if (StringRef(A->getValue()).getAsInteger(10, Level))
return createStringError(
"invalid value for --offload-compression-level=: '%s'",
A->getValue());
Comment on lines +1125 to +1132
for (auto &Image : Images) {
SmallVector<uint8_t, 0> CompressedBytes;
Expected<bool> DidCompressOrErr = offloading::compressSYCLDeviceImage(
ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(Image.Image->getBufferStart()),
Image.Image->getBufferSize()),
CompressedBytes, Level, /*Threshold=*/512, Verbose);
if (!DidCompressOrErr)
Comment on lines 83 to 92
// Offload models supported by this tool. The support basically means mapping
// a string representation given at the command line to a value from this
// enum.
enum OffloadKind {
// enum. Distinct from llvm::object::OffloadKind (in Object/OffloadBinary.h),
// which is the 16-bit bitmask stored in the OffloadBinary header
// (OFK_None/OFK_OpenMP/... = powers of two). This enum is a sequential
// command-line-parsed tag with an extra Host slot and First/Last sentinels,
// serialized as a uint8_t into the SYCL runtime's sycl_device_binary_struct
// Kind field.
enum OldOffloadKind {
Unknown = 0,
bviyer and others added 2 commits July 20, 2026 13:50
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Yury Plyakhin <yury.plyakhin@intel.com>
Comment thread clang/test/Driver/clang-linker-wrapper-zstd.cpp Outdated
Comment thread clang/test/Driver/clang-linker-wrapper-zstd.cpp Outdated
Comment thread clang/test/Driver/clang-linker-wrapper-zstd.cpp
if (!Args.hasArg(OPT_compress))
return Error::success();

int Level = 10;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The default compression level 10 is hardcoded here, and again as the default parameter in Utility.h line 249. Can there be a shared named constant, e.g. constexpr int DefaultSYCLCompressionLevel = 10 in Utility.h so a future change to the default only needs to happen in one place/the defaults across tool wrappers remain synced.

BIF_Native, // Native Image kind
BIF_SPIRV, // SPIR-V
BIF_LLVMBC, // LLVM bitcode
BIF_Compressed // zstd-compressed image; format-of-original unknown

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When the SYCL runtime decompresses the image, does it know whether the original image is SPIR-V, LLVM bitcode, or native?
Does the runtime always assume a fixed format post-decompression? (e.g. always SPIR-V/LLVM BC at this pipeline stage).
Would be helpful to document that information here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Q: Also, how can we differentiate between a JIT image and an AOT image that both get tagged BIF_Compressed ?

bviyer and others added 3 commits July 20, 2026 18:58
Co-authored-by: Srividya Sundaram <srividya.sundaram@intel.com>
Co-authored-by: Srividya Sundaram <srividya.sundaram@intel.com>
Co-authored-by: Srividya Sundaram <srividya.sundaram@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants