From 86f6b5065e86c8ec4556368ddee92f0851caf9f8 Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" Date: Wed, 22 Oct 2025 19:59:23 +0200 Subject: [PATCH] [Offload] Offload wrapper cleanup/refactoring (NFC) Addresses feedback from https://github.com/llvm/llvm-project/pull/147508#pullrequestreview-3272708203 : - Update access modifiers for SYCLWrapper members. - Update comments. - Update types. --- .../llvm/Frontend/Offloading/OffloadWrapper.h | 10 +- .../Frontend/Offloading/OffloadWrapper.cpp | 315 +++++++++--------- 2 files changed, 167 insertions(+), 158 deletions(-) diff --git a/llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h b/llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h index 24017492e30b2..dc99e29964afc 100644 --- a/llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h +++ b/llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h @@ -56,18 +56,18 @@ LLVM_ABI llvm::Error wrapHIPBinary(llvm::Module &M, llvm::ArrayRef Images, bool EmitSurfacesAndTextures = true); struct SYCLJITOptions { - // Target/compiler specific options that are suggested to use to "compile" - // program at runtime. + // Target/compiler specific options that are passed to the device compiler at + // runtime. std::string CompileOptions; - // Target/compiler specific options that are suggested to use to "link" - // program at runtime. + // Target/compiler specific options that are passed to the device linker at + // runtime. std::string LinkOptions; }; /// Wraps OffloadBinaries in the given \p Buffers into the module \p M /// as global symbols and registers the images with the SYCL Runtime. /// \param Options Compiler and linker options to be encoded for the later -/// use by a runtime for JIT compilation. +/// use by a runtime for JIT compilation. Not used for AOT. LLVM_ABI llvm::Error wrapSYCLBinaries(llvm::Module &M, llvm::ArrayRef Buffer, SYCLJITOptions Options = SYCLJITOptions()); diff --git a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp index 86060d1d2b0b3..288fa10fc04bb 100644 --- a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp +++ b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp @@ -640,15 +640,8 @@ void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc, } /// SYCLWrapper helper class that creates all LLVM IRs wrapping given images. -struct SYCLWrapper { - Module &M; - LLVMContext &C; - SYCLJITOptions Options; - - StructType *EntryTy = nullptr; - StructType *SyclDeviceImageTy = nullptr; - StructType *SyclBinDescTy = nullptr; - +class SYCLWrapper { +public: SYCLWrapper(Module &M, const SYCLJITOptions &Options) : M(M), C(M.getContext()), Options(Options) { EntryTy = offloading::getEntryTy(M); @@ -656,6 +649,115 @@ struct SYCLWrapper { SyclBinDescTy = getSyclBinDescTy(); } + /// Creates binary descriptor for the given device images. Binary descriptor + /// is an object that is passed to the offloading runtime at program startup + /// and it describes all device images available in the executable or shared + /// library. It is defined as follows: + /// + /// \code + /// __attribute__((visibility("hidden"))) + /// __tgt_offload_entry *__sycl_offload_entries_arr0[]; + /// ... + /// __attribute__((visibility("hidden"))) + /// __tgt_offload_entry *__sycl_offload_entries_arrN[]; + /// + /// __attribute__((visibility("hidden"))) + /// extern const char *CompileOptions = "..."; + /// ... + /// __attribute__((visibility("hidden"))) + /// extern const char *LinkOptions = "..."; + /// ... + /// + /// static const char Image0[] = { ... }; + /// ... + /// static const char ImageN[] = { ... }; + /// + /// static const __sycl.tgt_device_image Images[] = { + /// { + /// Version, // Version + /// OffloadKind, // OffloadKind + /// Format, // Format of the image. + // TripleString, // Arch + /// CompileOptions, // CompileOptions + /// LinkOptions, // LinkOptions + /// Image0, // ImageStart + /// Image0 + IMAGE0_SIZE, // ImageEnd + /// __sycl_offload_entries_arr0, // EntriesBegin + /// __sycl_offload_entries_arr0 + ENTRIES0_SIZE, // EntriesEnd + /// NULL, // PropertiesBegin + /// NULL, // PropertiesEnd + /// }, + /// ... + /// }; + /// + /// static const __sycl.tgt_bin_desc FatbinDesc = { + /// Version, //Version + /// sizeof(Images) / sizeof(Images[0]), //NumDeviceImages + /// Images, //DeviceImages + /// NULL, //HostEntriesBegin + /// NULL //HostEntriesEnd + /// }; + /// \endcode + /// + /// \returns Global variable that represents FatbinDesc. + GlobalVariable *createFatbinDesc(ArrayRef OffloadFiles) { + StringRef OffloadKindTag = ".sycl_offloading."; + SmallVector WrappedImages; + WrappedImages.reserve(OffloadFiles.size()); + for (size_t I = 0, E = OffloadFiles.size(); I != E; ++I) + WrappedImages.push_back( + wrapImage(*OffloadFiles[I].getBinary(), Twine(I), OffloadKindTag)); + + return combineWrappedImages(WrappedImages, OffloadKindTag); + } + + void createRegisterFatbinFunction(GlobalVariable *FatbinDesc) { + FunctionType *FuncTy = + FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); + Function *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, + Twine("sycl") + ".descriptor_reg", &M); + Func->setSection(".text.startup"); + + // Get RegFuncName function declaration. + FunctionType *RegFuncTy = + FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C), + /*isVarArg=*/false); + FunctionCallee RegFuncC = + M.getOrInsertFunction("__sycl_register_lib", RegFuncTy); + + // Construct function body. + IRBuilder Builder(BasicBlock::Create(C, "entry", Func)); + Builder.CreateCall(RegFuncC, FatbinDesc); + Builder.CreateRetVoid(); + + // Add this function to constructors. + appendToGlobalCtors(M, Func, /*Priority*/ 1); + } + + void createUnregisterFunction(GlobalVariable *FatbinDesc) { + FunctionType *FuncTy = + FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); + Function *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, + "sycl.descriptor_unreg", &M); + Func->setSection(".text.startup"); + + // Get UnregFuncName function declaration. + FunctionType *UnRegFuncTy = + FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C), + /*isVarArg=*/false); + FunctionCallee UnRegFuncC = + M.getOrInsertFunction("__sycl_unregister_lib", UnRegFuncTy); + + // Construct function body + IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); + Builder.CreateCall(UnRegFuncC, FatbinDesc); + Builder.CreateRetVoid(); + + // Add this function to global destructors. + appendToGlobalDtors(M, Func, /*Priority*/ 1); + } + +private: IntegerType *getSizeTTy() { switch (M.getDataLayout().getPointerSize()) { case 4: @@ -678,28 +780,28 @@ struct SYCLWrapper { /// SYCL specific image descriptor type. /// \code /// struct __sycl.tgt_device_image { - /// // version of this structure - for backward compatibility; + /// // Version of this structure - for backward compatibility; /// // all modifications which change order/type/offsets of existing fields /// // should increment the version. /// uint16_t Version; - /// // the kind of offload model the image employs. + /// // The kind of offload model the image employs. /// uint8_t OffloadKind; - /// // format of the image data - SPIRV, LLVMIR bitcode, etc + /// // Format of the image data - SPIRV, LLVMIR bitcode, etc. /// uint8_t Format; - /// // null-terminated string representation of the device's target - /// // architecture + /// // Null-terminated string representation of the device's target + /// // architecture. /// const char *Arch; - /// // a null-terminated string; target- and compiler-specific options - /// // which are suggested to use to "compile" program at runtime + /// // A null-terminated string; target- and compiler-specific options + /// // which are passed to the device compiler at runtime. /// const char *CompileOptions; - /// // a null-terminated string; target- and compiler-specific options - /// // which are suggested to use to "link" program at runtime + /// // A null-terminated string; target- and compiler-specific options + /// // which are passed to the device linker at runtime. /// const char *LinkOptions; - /// // Pointer to the device binary image start + /// // Pointer to the device binary image start. /// void *ImageStart; - /// // Pointer to the device binary image end + /// // Pointer to the device binary image end. /// void *ImageEnd; - /// // the entry table + /// // The entry table. /// __tgt_offload_entry *EntriesBegin; /// __tgt_offload_entry *EntriesEnd; /// const char *PropertiesBegin; @@ -753,13 +855,14 @@ struct SYCLWrapper { GlobalVariable *addGlobalArrayVariable(const Twine &Name, ArrayRef Initializer, const Twine &Section = "") { - auto *Arr = ConstantDataArray::get(M.getContext(), Initializer); - auto *Var = new GlobalVariable(M, Arr->getType(), /*isConstant*/ true, - GlobalVariable::InternalLinkage, Arr, Name); + Constant *Arr = ConstantDataArray::get(M.getContext(), Initializer); + GlobalVariable *Var = + new GlobalVariable(M, Arr->getType(), /*isConstant*/ true, + GlobalVariable::InternalLinkage, Arr, Name); Var->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); SmallVector NameBuf; - auto SectionName = Section.toStringRef(NameBuf); + StringRef SectionName = Section.toStringRef(NameBuf); if (!SectionName.empty()) Var->setSection(SectionName); return Var; @@ -771,10 +874,10 @@ struct SYCLWrapper { std::pair addArrayToModule(ArrayRef Buf, const Twine &Name, const Twine &Section = "") { - auto *Var = addGlobalArrayVariable(Name, Buf, Section); - auto *ImageB = ConstantExpr::getGetElementPtr(Var->getValueType(), Var, - getSizetConstPair(0, 0)); - auto *ImageE = ConstantExpr::getGetElementPtr( + GlobalVariable *Var = addGlobalArrayVariable(Name, Buf, Section); + Constant *ImageB = ConstantExpr::getGetElementPtr(Var->getValueType(), Var, + getSizetConstPair(0, 0)); + Constant *ImageE = ConstantExpr::getGetElementPtr( Var->getValueType(), Var, getSizetConstPair(0, Buf.size())); return std::make_pair(ImageB, ImageE); } @@ -783,9 +886,9 @@ struct SYCLWrapper { /// \returns Constant pointer to the added data. The pointer type does not /// carry size information. Constant *addRawDataToModule(ArrayRef Data, const Twine &Name) { - auto *Var = addGlobalArrayVariable(Name, Data); - auto *DataPtr = ConstantExpr::getGetElementPtr(Var->getValueType(), Var, - getSizetConstPair(0, 0)); + GlobalVariable *Var = addGlobalArrayVariable(Name, Data); + Constant *DataPtr = ConstantExpr::getGetElementPtr(Var->getValueType(), Var, + getSizetConstPair(0, 0)); return DataPtr; } @@ -795,11 +898,12 @@ struct SYCLWrapper { /// \returns Link-time constant pointer (constant expr) to that /// variable. Constant *addStringToModule(StringRef Str, const Twine &Name) { - auto *Arr = ConstantDataArray::getString(C, Str); - auto *Var = new GlobalVariable(M, Arr->getType(), /*isConstant*/ true, - GlobalVariable::InternalLinkage, Arr, Name); + Constant *Arr = ConstantDataArray::getString(C, Str); + GlobalVariable *Var = + new GlobalVariable(M, Arr->getType(), /*isConstant*/ true, + GlobalVariable::InternalLinkage, Arr, Name); Var->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - auto *Zero = ConstantInt::get(getSizeTTy(), 0); + ConstantInt *Zero = ConstantInt::get(getSizeTTy(), 0); Constant *ZeroZero[] = {Zero, Zero}; return ConstantExpr::getGetElementPtr(Var->getValueType(), Var, ZeroZero); } @@ -823,15 +927,15 @@ struct SYCLWrapper { EntriesInits.push_back(GV->getInitializer()); } - auto *Arr = ConstantArray::get(ArrayType::get(EntryTy, EntriesInits.size()), - EntriesInits); - auto *EntriesGV = new GlobalVariable(M, Arr->getType(), /*isConstant*/ true, - GlobalVariable::InternalLinkage, Arr, - OffloadKindTag + "entries_arr"); + Constant *Arr = ConstantArray::get( + ArrayType::get(EntryTy, EntriesInits.size()), EntriesInits); + GlobalVariable *EntriesGV = new GlobalVariable( + M, Arr->getType(), /*isConstant*/ true, GlobalVariable::InternalLinkage, + Arr, OffloadKindTag + "entries_arr"); - auto *EntriesB = ConstantExpr::getGetElementPtr( + Constant *EntriesB = ConstantExpr::getGetElementPtr( EntriesGV->getValueType(), EntriesGV, getSizetConstPair(0, 0)); - auto *EntriesE = ConstantExpr::getGetElementPtr( + Constant *EntriesE = ConstantExpr::getGetElementPtr( EntriesGV->getValueType(), EntriesGV, getSizetConstPair(0, EntriesInits.size())); return std::make_pair(EntriesB, EntriesE); @@ -871,6 +975,9 @@ struct SYCLWrapper { // For SYCL images offload entries are defined here per image. std::pair ImageEntriesPtrs = initOffloadEntriesPerImage(OB.getString("symbols"), OffloadKindTag); + + // .first and .second arguments below correspond to start and end pointers + // respectively. Constant *WrappedBinary = ConstantStruct::get( SyclDeviceImageTy, Version, OffloadKindConstant, ImageKindConstant, TripleConstant, CompileOptions, LinkOptions, Binary.first, @@ -882,23 +989,23 @@ struct SYCLWrapper { GlobalVariable *combineWrappedImages(ArrayRef WrappedImages, StringRef OffloadKindTag) { - auto *ImagesData = ConstantArray::get( + Constant *ImagesData = ConstantArray::get( ArrayType::get(SyclDeviceImageTy, WrappedImages.size()), WrappedImages); - auto *ImagesGV = + GlobalVariable *ImagesGV = new GlobalVariable(M, ImagesData->getType(), /*isConstant*/ true, GlobalValue::InternalLinkage, ImagesData, Twine(OffloadKindTag) + "device_images"); ImagesGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - auto *Zero = ConstantInt::get(getSizeTTy(), 0); + ConstantInt *Zero = ConstantInt::get(getSizeTTy(), 0); Constant *ZeroZero[] = {Zero, Zero}; - auto *ImagesB = ConstantExpr::getGetElementPtr(ImagesGV->getValueType(), - ImagesGV, ZeroZero); + Constant *ImagesB = ConstantExpr::getGetElementPtr(ImagesGV->getValueType(), + ImagesGV, ZeroZero); Constant *EntriesB = Constant::getNullValue(PointerType::getUnqual(C)); Constant *EntriesE = Constant::getNullValue(PointerType::getUnqual(C)); static constexpr uint16_t BinDescStructVersion = 1; - auto *DescInit = ConstantStruct::get( + Constant *DescInit = ConstantStruct::get( SyclBinDescTy, ConstantInt::get(Type::getInt16Ty(C), BinDescStructVersion), ConstantInt::get(Type::getInt16Ty(C), WrappedImages.size()), ImagesB, @@ -909,111 +1016,13 @@ struct SYCLWrapper { Twine(OffloadKindTag) + "descriptor"); } - /// Creates binary descriptor for the given device images. Binary descriptor - /// is an object that is passed to the offloading runtime at program startup - /// and it describes all device images available in the executable or shared - /// library. It is defined as follows: - /// - /// \code - /// __attribute__((visibility("hidden"))) - /// __tgt_offload_entry *__sycl_offload_entries_arr0[]; - /// ... - /// __attribute__((visibility("hidden"))) - /// __tgt_offload_entry *__sycl_offload_entries_arrN[]; - /// - /// __attribute__((visibility("hidden"))) - /// extern const char *CompileOptions = "..."; - /// ... - /// __attribute__((visibility("hidden"))) - /// extern const char *LinkOptions = "..."; - /// ... - /// - /// static const char Image0[] = { ... }; - /// ... - /// static const char ImageN[] = { ... }; - /// - /// static const __sycl.tgt_device_image Images[] = { - /// { - /// Version, // Version - /// OffloadKind, // OffloadKind - /// Format, // Format of the image. - // TripleString, // Arch - /// CompileOptions, // CompileOptions - /// LinkOptions, // LinkOptions - /// Image0, // ImageStart - /// Image0 + IMAGE0_SIZE, // ImageEnd - /// __sycl_offload_entries_arr0, // EntriesBegin - /// __sycl_offload_entries_arr0 + ENTRIES0_SIZE, // EntriesEnd - /// NULL, // PropertiesBegin - /// NULL, // PropertiesEnd - /// }, - /// ... - /// }; - /// - /// static const __sycl.tgt_bin_desc FatbinDesc = { - /// Version, //Version - /// sizeof(Images) / sizeof(Images[0]), //NumDeviceImages - /// Images, //DeviceImages - /// NULL, //HostEntriesBegin - /// NULL //HostEntriesEnd - /// }; - /// \endcode - /// - /// \returns Global variable that represents FatbinDesc. - GlobalVariable *createFatbinDesc(ArrayRef OffloadFiles) { - StringRef OffloadKindTag = ".sycl_offloading."; - SmallVector WrappedImages; - WrappedImages.reserve(OffloadFiles.size()); - for (size_t I = 0, E = OffloadFiles.size(); I != E; ++I) - WrappedImages.push_back( - wrapImage(*OffloadFiles[I].getBinary(), Twine(I), OffloadKindTag)); - - return combineWrappedImages(WrappedImages, OffloadKindTag); - } - - void createRegisterFatbinFunction(GlobalVariable *FatbinDesc) { - auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); - auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, - Twine("sycl") + ".descriptor_reg", &M); - Func->setSection(".text.startup"); - - // Get RegFuncName function declaration. - auto *RegFuncTy = - FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C), - /*isVarArg=*/false); - FunctionCallee RegFuncC = - M.getOrInsertFunction("__sycl_register_lib", RegFuncTy); - - // Construct function body - IRBuilder Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(RegFuncC, FatbinDesc); - Builder.CreateRetVoid(); - - // Add this function to constructors. - appendToGlobalCtors(M, Func, /*Priority*/ 1); - } - - void createUnregisterFunction(GlobalVariable *FatbinDesc) { - auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); - auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, - "sycl.descriptor_unreg", &M); - Func->setSection(".text.startup"); - - // Get UnregFuncName function declaration. - auto *UnRegFuncTy = - FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C), - /*isVarArg=*/false); - FunctionCallee UnRegFuncC = - M.getOrInsertFunction("__sycl_unregister_lib", UnRegFuncTy); - - // Construct function body - IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(UnRegFuncC, FatbinDesc); - Builder.CreateRetVoid(); + Module &M; + LLVMContext &C; + SYCLJITOptions Options; - // Add this function to global destructors. - appendToGlobalDtors(M, Func, /*Priority*/ 1); - } + StructType *EntryTy = nullptr; + StructType *SyclDeviceImageTy = nullptr; + StructType *SyclBinDescTy = nullptr; }; // end of SYCLWrapper } // namespace