diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 8a1212f2272e8..2ef4dc236d091 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/Cuda.h" #include "clang/CodeGen/CodeGenABITypes.h" #include "clang/CodeGen/ConstantInitBuilder.h" +#include "llvm/Frontend/Offloading/Utility.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -1129,33 +1130,32 @@ void CGNVCUDARuntime::transformManagedVars() { // registered. The linker will provide a pointer to this section so we can // register the symbols with the linked device image. void CGNVCUDARuntime::createOffloadingEntries() { - llvm::OpenMPIRBuilder OMPBuilder(CGM.getModule()); - OMPBuilder.initialize(); - StringRef Section = CGM.getLangOpts().HIP ? "hip_offloading_entries" : "cuda_offloading_entries"; + llvm::Module &M = CGM.getModule(); for (KernelInfo &I : EmittedKernels) - OMPBuilder.emitOffloadingEntry(KernelHandles[I.Kernel->getName()], - getDeviceSideName(cast(I.D)), 0, - DeviceVarFlags::OffloadGlobalEntry, Section); + llvm::offloading::emitOffloadingEntry( + M, KernelHandles[I.Kernel->getName()], + getDeviceSideName(cast(I.D)), 0, + DeviceVarFlags::OffloadGlobalEntry, Section); for (VarInfo &I : DeviceVars) { uint64_t VarSize = CGM.getDataLayout().getTypeAllocSize(I.Var->getValueType()); if (I.Flags.getKind() == DeviceVarFlags::Variable) { - OMPBuilder.emitOffloadingEntry( - I.Var, getDeviceSideName(I.D), VarSize, + llvm::offloading::emitOffloadingEntry( + M, I.Var, getDeviceSideName(I.D), VarSize, I.Flags.isManaged() ? DeviceVarFlags::OffloadGlobalManagedEntry : DeviceVarFlags::OffloadGlobalEntry, Section); } else if (I.Flags.getKind() == DeviceVarFlags::Surface) { - OMPBuilder.emitOffloadingEntry(I.Var, getDeviceSideName(I.D), VarSize, - DeviceVarFlags::OffloadGlobalSurfaceEntry, - Section); + llvm::offloading::emitOffloadingEntry( + M, I.Var, getDeviceSideName(I.D), VarSize, + DeviceVarFlags::OffloadGlobalSurfaceEntry, Section); } else if (I.Flags.getKind() == DeviceVarFlags::Texture) { - OMPBuilder.emitOffloadingEntry(I.Var, getDeviceSideName(I.D), VarSize, - DeviceVarFlags::OffloadGlobalTextureEntry, - Section); + llvm::offloading::emitOffloadingEntry( + M, I.Var, getDeviceSideName(I.D), VarSize, + DeviceVarFlags::OffloadGlobalTextureEntry, Section); } } } diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index d67ce982d78ac..da98848e3b443 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS Extensions FrontendHLSL FrontendOpenMP + FrontendOffloading HIPStdPar IPO IRPrinter diff --git a/llvm/include/llvm/Frontend/Offloading/Utility.h b/llvm/include/llvm/Frontend/Offloading/Utility.h new file mode 100644 index 0000000000000..f74f9e3ff119f --- /dev/null +++ b/llvm/include/llvm/Frontend/Offloading/Utility.h @@ -0,0 +1,37 @@ +//===- Utility.h - Collection of geneirc offloading utilities -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Module.h" +#include "llvm/Object/OffloadBinary.h" + +namespace llvm { +namespace offloading { + +/// Create an offloading section struct used to register this global at +/// runtime. +/// +/// Type struct __tgt_offload_entry{ +/// void *addr; // Pointer to the offload entry info. +/// // (function or global) +/// char *name; // Name of the function or global. +/// size_t size; // Size of the entry info (0 if it a function). +/// int32_t flags; +/// int32_t reserved; +/// }; +/// +/// \param M The module to be used +/// \param Addr The pointer to the global being registered. +/// \param Name The symbol name associated with the global. +/// \param Size The size in bytes of the global (0 for functions). +/// \param Flags Flags associated with the entry. +/// \param SectionName The section this entry will be placed at. +void emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name, + uint64_t Size, int32_t Flags, StringRef SectionName); + +} // namespace offloading +} // namespace llvm diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h index 00b4707a7f820..c2cfdfd32324d 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -1358,27 +1358,6 @@ class OpenMPIRBuilder { /// Value. GlobalValue *createGlobalFlag(unsigned Value, StringRef Name); - /// Create an offloading section struct used to register this global at - /// runtime. - /// - /// Type struct __tgt_offload_entry{ - /// void *addr; // Pointer to the offload entry info. - /// // (function or global) - /// char *name; // Name of the function or global. - /// size_t size; // Size of the entry info (0 if it a function). - /// int32_t flags; - /// int32_t reserved; - /// }; - /// - /// \param Addr The pointer to the global being registered. - /// \param Name The symbol name associated with the global. - /// \param Size The size in bytes of the global (0 for functions). - /// \param Flags Flags associated with the entry. - /// \param SectionName The section this entry will be placed at. - void emitOffloadingEntry(Constant *Addr, StringRef Name, uint64_t Size, - int32_t Flags, - StringRef SectionName = "omp_offloading_entries"); - /// Generate control flow and cleanup for cancellation. /// /// \param CancelFlag Flag indicating if the cancellation is performed. diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 4823c4cc6b833..39780e7c8934c 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -88,8 +88,6 @@ __OMP_ARRAY_TYPE(Int32Arr3, Int32, 3) OMP_STRUCT_TYPE(VarName, "struct." #Name, Packed, __VA_ARGS__) __OMP_STRUCT_TYPE(Ident, ident_t, false, Int32, Int32, Int32, Int32, Int8Ptr) -__OMP_STRUCT_TYPE(OffloadEntry, __tgt_offload_entry, false, Int8Ptr, Int8Ptr, SizeTy, - Int32, Int32) __OMP_STRUCT_TYPE(KernelArgs, __tgt_kernel_arguments, false, Int32, Int32, VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr, Int64, Int64, Int32Arr3Ty, Int32Arr3Ty, Int32) diff --git a/llvm/lib/Frontend/CMakeLists.txt b/llvm/lib/Frontend/CMakeLists.txt index fa48c975a8b3e..5ef092e0a1a9e 100644 --- a/llvm/lib/Frontend/CMakeLists.txt +++ b/llvm/lib/Frontend/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(HLSL) add_subdirectory(OpenACC) add_subdirectory(OpenMP) +add_subdirectory(Offloading) diff --git a/llvm/lib/Frontend/Offloading/CMakeLists.txt b/llvm/lib/Frontend/Offloading/CMakeLists.txt new file mode 100644 index 0000000000000..25eb24785732e --- /dev/null +++ b/llvm/lib/Frontend/Offloading/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_component_library(LLVMFrontendOffloading + Utility.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend + + DEPENDS + intrinsics_gen + + LINK_COMPONENTS + Core + Support + TransformUtils +) diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp new file mode 100644 index 0000000000000..48f0015bac4e3 --- /dev/null +++ b/llvm/lib/Frontend/Offloading/Utility.cpp @@ -0,0 +1,67 @@ +//===- Utility.cpp ------ Collection of geneirc offloading utilities ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Frontend/Offloading/Utility.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Value.h" + +using namespace llvm; +using namespace llvm::offloading; + +// TODO: Export this to the linker wrapper code registration. +static StructType *getEntryTy(Module &M) { + LLVMContext &C = M.getContext(); + StructType *EntryTy = + StructType::getTypeByName(C, "struct.__tgt_offload_entry"); + if (!EntryTy) + EntryTy = StructType::create("struct.__tgt_offload_entry", + Type::getInt8PtrTy(C), Type::getInt8PtrTy(C), + M.getDataLayout().getIntPtrType(C), + Type::getInt32Ty(C), Type::getInt32Ty(C)); + return EntryTy; +} + +// TODO: Rework this interface to be more generic. +void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name, + uint64_t Size, int32_t Flags, + StringRef SectionName) { + Type *Int8PtrTy = Type::getInt8PtrTy(M.getContext()); + Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext()); + + Constant *AddrName = ConstantDataArray::getString(M.getContext(), Name); + + // Create the constant string used to look up the symbol in the device. + auto *Str = + new llvm::GlobalVariable(M, AddrName->getType(), /*isConstant=*/true, + llvm::GlobalValue::InternalLinkage, AddrName, + ".omp_offloading.entry_name"); + Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + + // Construct the offloading entry. + Constant *EntryData[] = { + ConstantExpr::getPointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy), + ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, Int8PtrTy), + ConstantInt::get(SizeTy, Size), + ConstantInt::get(Int32Ty, Flags), + ConstantInt::get(Int32Ty, 0), + }; + Constant *EntryInitializer = ConstantStruct::get(getEntryTy(M), EntryData); + + auto *Entry = new GlobalVariable( + M, getEntryTy(M), + /*isConstant=*/true, GlobalValue::WeakAnyLinkage, EntryInitializer, + ".omp_offloading.entry." + Name, nullptr, GlobalValue::NotThreadLocal, + M.getDataLayout().getDefaultGlobalsAddressSpace()); + + // The entry has to be created in the section the linker expects it to be. + Entry->setSection(SectionName); + Entry->setAlignment(Align(1)); +} diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt index a2eedabc3ed69..67aedf5c2b61a 100644 --- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt +++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt @@ -20,4 +20,5 @@ add_llvm_component_library(LLVMFrontendOpenMP MC Scalar BitReader + FrontendOffloading ) diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index 5b24e9fe2e0c5..62c97ff7f2925 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -23,6 +23,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Frontend/Offloading/Utility.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -958,44 +959,6 @@ OpenMPIRBuilder::createCancel(const LocationDescription &Loc, return Builder.saveIP(); } -void OpenMPIRBuilder::emitOffloadingEntry(Constant *Addr, StringRef Name, - uint64_t Size, int32_t Flags, - StringRef SectionName) { - Type *Int8PtrTy = Type::getInt8PtrTy(M.getContext()); - Type *Int32Ty = Type::getInt32Ty(M.getContext()); - Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext()); - - Constant *AddrName = ConstantDataArray::getString(M.getContext(), Name); - - // Create the constant string used to look up the symbol in the device. - auto *Str = - new llvm::GlobalVariable(M, AddrName->getType(), /*isConstant=*/true, - llvm::GlobalValue::InternalLinkage, AddrName, - ".omp_offloading.entry_name"); - Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - // Construct the offloading entry. - Constant *EntryData[] = { - ConstantExpr::getPointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy), - ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, Int8PtrTy), - ConstantInt::get(SizeTy, Size), - ConstantInt::get(Int32Ty, Flags), - ConstantInt::get(Int32Ty, 0), - }; - Constant *EntryInitializer = - ConstantStruct::get(OpenMPIRBuilder::OffloadEntry, EntryData); - - auto *Entry = new GlobalVariable( - M, OpenMPIRBuilder::OffloadEntry, - /* isConstant = */ true, GlobalValue::WeakAnyLinkage, EntryInitializer, - ".omp_offloading.entry." + Name, nullptr, GlobalValue::NotThreadLocal, - M.getDataLayout().getDefaultGlobalsAddressSpace()); - - // The entry has to be created in the section the linker expects it to be. - Entry->setSection(SectionName); - Entry->setAlignment(Align(1)); -} - OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitTargetKernel( const LocationDescription &Loc, InsertPointTy AllocaIP, Value *&Return, Value *Ident, Value *DeviceID, Value *NumTeams, Value *NumThreads, @@ -5928,7 +5891,9 @@ void OpenMPIRBuilder::createOffloadEntry(Constant *ID, Constant *Addr, GlobalValue::LinkageTypes, StringRef Name) { if (!Config.isGPU()) { - emitOffloadingEntry(ID, Name.empty() ? Addr->getName() : Name, Size, Flags); + llvm::offloading::emitOffloadingEntry( + M, ID, Name.empty() ? Addr->getName() : Name, Size, Flags, + "omp_offloading_entries"); return; } // TODO: Add support for global variables on the device after declare target