Skip to content

Commit

Permalink
[Offload] Only initialize a plugin if it is needed (llvm#92765)
Browse files Browse the repository at this point in the history
  relands 21f3a60 [Offload] Only initialize a plugin if it is needed (llvm#92765)
  includes f284af  [Offload][Fix] Fix lazy initialization with multiple images

includes fix in patchset 3 to resolve 3 smoke tests:
  currently fails smoke:
    multi-image
    multi-image3
    targetid_multi_image

Change-Id: Ic1890f6e765fd9a91d00f1b85e36f26382b8c608
  • Loading branch information
ronlieb committed May 29, 2024
1 parent 0c9bbb8 commit dc6e68a
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 37 deletions.
4 changes: 0 additions & 4 deletions offload/plugins-nextgen/common/include/JIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ struct JITEngine {
process(const __tgt_device_image &Image,
target::plugin::GenericDeviceTy &Device);

/// Return true if \p Image is a bitcode image that can be JITed for the given
/// architecture.
Expected<bool> checkBitcodeImage(StringRef Buffer) const;

private:
/// Compile the bitcode image \p Image and generate the binary image that can
/// be loaded to the target device of the triple \p Triple architecture \p
Expand Down
12 changes: 11 additions & 1 deletion offload/plugins-nextgen/common/include/PluginInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,10 @@ struct GenericPluginTy {
/// given target. Returns true if the \p Image is compatible with the plugin.
Expected<bool> checkELFImage(StringRef Image) const;

/// Return true if the \p Image can be compiled to run on the platform's
/// target architecture.
Expected<bool> checkBitcodeImage(StringRef Image) const;

/// Indicate if an image is compatible with the plugin devices. Notice that
/// this function may be called before actually initializing the devices. So
/// we could not move this function into GenericDeviceTy.
Expand All @@ -1186,8 +1190,11 @@ struct GenericPluginTy {
public:
// TODO: This plugin interface needs to be cleaned up.

/// Returns true if the plugin has been initialized.
int32_t is_initialized() const;

/// Returns non-zero if the provided \p Image can be executed by the runtime.
int32_t is_valid_binary(__tgt_device_image *Image);
int32_t is_valid_binary(__tgt_device_image *Image, bool Initialized = true);

/// Checks if the image is not supported.
void check_invalid_image(__tgt_device_image *InvalidImage);
Expand Down Expand Up @@ -1352,6 +1359,9 @@ struct GenericPluginTy {
bool isEagerMaps);

private:
/// Indicates if the platform runtime has been fully initialized.
bool Initialized = false;

/// Number of devices available for the plugin.
int32_t NumDevices = 0;

Expand Down
16 changes: 0 additions & 16 deletions offload/plugins-nextgen/common/src/JIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,19 +323,3 @@ JITEngine::process(const __tgt_device_image &Image,

return &Image;
}

Expected<bool> JITEngine::checkBitcodeImage(StringRef Buffer) const {
TimeTraceScope TimeScope("Check bitcode image");

assert(identify_magic(Buffer) == file_magic::bitcode &&
"Input is not bitcode");

LLVMContext Context;
auto ModuleOrErr = getLazyBitcodeModule(MemoryBufferRef(Buffer, ""), Context,
/*ShouldLazyLoadMetadata=*/true);
if (!ModuleOrErr)
return ModuleOrErr.takeError();
Module &M = **ModuleOrErr;

return Triple(M.getTargetTriple()).getArch() == TT.getArch();
}
42 changes: 36 additions & 6 deletions offload/plugins-nextgen/common/src/PluginInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "omp-tools.h"
#endif

#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
Expand Down Expand Up @@ -1607,6 +1608,7 @@ Error GenericPluginTy::init() {
if (!NumDevicesOrErr)
return NumDevicesOrErr.takeError();

Initialized = true;
NumDevices = *NumDevicesOrErr;
if (NumDevices == 0)
return Plugin::success();
Expand Down Expand Up @@ -1692,14 +1694,27 @@ Expected<bool> GenericPluginTy::checkELFImage(StringRef Image) const {
if (!MachineOrErr)
return MachineOrErr.takeError();

if (!*MachineOrErr)
return MachineOrErr;
}

Expected<bool> GenericPluginTy::checkBitcodeImage(StringRef Image) const {
if (identify_magic(Image) != file_magic::bitcode)
return false;

// Perform plugin-dependent checks for the specific architecture if needed.
return isELFCompatible(Image);
LLVMContext Context;
auto ModuleOrErr = getLazyBitcodeModule(MemoryBufferRef(Image, ""), Context,
/*ShouldLazyLoadMetadata=*/true);
if (!ModuleOrErr)
return ModuleOrErr.takeError();
Module &M = **ModuleOrErr;

return Triple(M.getTargetTriple()).getArch() == getTripleArch();
}

int32_t GenericPluginTy::is_valid_binary(__tgt_device_image *Image) {
int32_t GenericPluginTy::is_initialized() const { return Initialized; }

int32_t GenericPluginTy::is_valid_binary(__tgt_device_image *Image,
bool Initialized) {
auto T = logger::log<int32_t>(__func__, Image);
int32_t R = [&]() {
StringRef Buffer(reinterpret_cast<const char *>(Image->ImageStart),
Expand All @@ -1719,10 +1734,25 @@ int32_t GenericPluginTy::is_valid_binary(__tgt_device_image *Image) {
auto MatchOrErr = checkELFImage(Buffer);
if (Error Err = MatchOrErr.takeError())
return HandleError(std::move(Err));
return *MatchOrErr;
if (!Initialized || !*MatchOrErr)
return *MatchOrErr;

// Perform plugin-dependent checks for the specific architecture if needed.
auto CompatibleOrErr = isELFCompatible(Buffer);
if (Error Err = CompatibleOrErr.takeError())
return HandleError(std::move(Err));
return *CompatibleOrErr;
}
case file_magic::offload_binary: {
// Perform plugin-dependent checks for the specific architecture if needed.
auto CompatibleOrErr = isELFCompatible(Buffer);
if (Error Err = CompatibleOrErr.takeError())
return HandleError(std::move(Err));
return *CompatibleOrErr;
}

case file_magic::bitcode: {
auto MatchOrErr = getJIT().checkBitcodeImage(Buffer);
auto MatchOrErr = checkBitcodeImage(Buffer);
if (Error Err = MatchOrErr.takeError())
return HandleError(std::move(Err));
return *MatchOrErr;
Expand Down
34 changes: 24 additions & 10 deletions offload/src/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,8 @@ void PluginManager::init() {
// Attempt to create an instance of each supported plugin.
#define PLUGIN_TARGET(Name) \
do { \
auto Plugin = std::unique_ptr<GenericPluginTy>(createPlugin_##Name()); \
if (auto Err = Plugin->init()) { \
[[maybe_unused]] std::string InfoMsg = toString(std::move(Err)); \
DP("Failed to init plugin: %s\n", InfoMsg.c_str()); \
} else { \
DP("Registered plugin %s with %d visible device(s)\n", \
Plugin->getName(), Plugin->number_of_devices()); \
Plugins.emplace_back(std::move(Plugin)); \
} \
Plugins.emplace_back( \
std::unique_ptr<GenericPluginTy>(createPlugin_##Name())); \
} while (false);
#include "Shared/Targets.def"

Expand Down Expand Up @@ -199,6 +192,27 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) {
if (Entry.flags == OMP_REGISTER_REQUIRES)
PM->addRequirements(Entry.data);

// Initialize all the plugins that have associated images.
for (auto &Plugin : Plugins) {
// Extract the exectuable image and extra information if availible.
for (int32_t i = 0; i < Desc->NumDeviceImages; ++i) {
if (Plugin->is_initialized())
continue;

if (!Plugin->is_valid_binary(&Desc->DeviceImages[i],
/*Initialized=*/false))
continue;

if (auto Err = Plugin->init()) {
[[maybe_unused]] std::string InfoMsg = toString(std::move(Err));
DP("Failed to init plugin: %s\n", InfoMsg.c_str());
} else {
DP("Registered plugin %s with %d visible device(s)\n",
Plugin->getName(), Plugin->number_of_devices());
}
}
}

// Extract the exectuable image and extra information if availible.
for (int32_t i = 0; i < Desc->NumDeviceImages; ++i)
PM->addDeviceImage(*Desc, Desc->DeviceImages[i]);
Expand All @@ -217,7 +231,7 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) {
if (!R.number_of_devices())
continue;

if (!R.is_valid_binary(Img)) {
if (!R.is_valid_binary(Img, /*Initialized=*/true)) {
DP("Image " DPxMOD " is NOT compatible with RTL %s!\n",
DPxPTR(Img->ImageStart), R.getName());
continue;
Expand Down

0 comments on commit dc6e68a

Please sign in to comment.