SWDEV-540645 - use single path for code object loading (#773)

* use single path for code object loading
* Remove printf
* Address review comments
* Fix the declaration of ihipMallocManaged

[ROCm/clr commit: d7f90a3120]
Этот коммит содержится в:
Chaudhary, Jatin Jaikishan
2025-08-12 10:45:18 +01:00
коммит произвёл GitHub
родитель 0e0ca48a6a
Коммит 7fe61f9556
5 изменённых файлов: 503 добавлений и 1201 удалений
+2 -580
Просмотреть файл
@@ -35,584 +35,6 @@ namespace hip {
hipError_t ihipFree(void* ptr);
// forward declaration of methods required for managed variables
hipError_t ihipMallocManaged(void** ptr, size_t size, size_t align = 0, bool use_host_ptr = 0);
namespace {
// In uncompressed mode
constexpr char kOffloadBundleUncompressedMagicStr[] = "__CLANG_OFFLOAD_BUNDLE__";
static constexpr size_t kOffloadBundleUncompressedMagicStrSize =
sizeof(kOffloadBundleUncompressedMagicStr);
// In compressed mode
constexpr char kOffloadBundleCompressedMagicStr[] = "CCOB";
static constexpr size_t kOffloadBundleCompressedMagicStrSize =
sizeof(kOffloadBundleCompressedMagicStr);
constexpr char kOffloadKindHip[] = "hip";
constexpr char kOffloadKindHipv4[] = "hipv4";
constexpr char kOffloadKindHcc[] = "hcc";
constexpr char kAmdgcnTargetTriple[] = "amdgcn-amd-amdhsa-";
constexpr char kHipFatBinName[] = "hipfatbin";
constexpr char kHipFatBinName_[] = "hipfatbin-";
constexpr char kOffloadKindHipv4_[] = "hipv4-"; // bundled code objects need the prefix
constexpr char kOffloadHipV4FatBinName_[] = "hipfatbin-hipv4-";
// Clang Offload bundler description & Header in uncompressed mode.
struct __ClangOffloadBundleInfo {
uint64_t offset;
uint64_t size;
uint64_t bundleEntryIdSize;
const char bundleEntryId[1];
};
struct __ClangOffloadBundleUncompressedHeader {
const char magic[kOffloadBundleUncompressedMagicStrSize - 1];
uint64_t numOfCodeObjects;
__ClangOffloadBundleInfo desc[1];
};
// Clang Offload bundler description & Header in compressed mode.
struct __ClangOffloadBundleCompressedHeader {
const char magic[kOffloadBundleCompressedMagicStrSize - 1];
uint16_t versionNumber;
uint16_t compressionMethod;
uint32_t totalSize;
uint32_t uncompressedBinarySize;
uint64_t Hash;
const char compressedBinarydesc[1];
};
} // namespace
bool CodeObject::IsClangOffloadMagicBundle(const void* data, bool& isCompressed) {
std::string magic(reinterpret_cast<const char*>(data),
kOffloadBundleUncompressedMagicStrSize - 1);
if (!magic.compare(kOffloadBundleUncompressedMagicStr)) {
isCompressed = false;
return true;
}
std::string magic1(reinterpret_cast<const char*>(data),
kOffloadBundleCompressedMagicStrSize - 1);
if (!magic1.compare(kOffloadBundleCompressedMagicStr)) {
isCompressed = true;
return true;
}
return false;
}
uint32_t CodeObject::getGenericVersion(const void* image) {
const Elf64_Ehdr* ehdr = reinterpret_cast<const Elf64_Ehdr*>(image);
return (ehdr->e_machine == EM_AMDGPU && ehdr->e_ident[EI_OSABI] == ELFOSABI_AMDGPU_HSA &&
ehdr->e_ident[EI_ABIVERSION] == ELFABIVERSION_AMDGPU_HSA_V6) ?
((ehdr->e_flags & EF_AMDGPU_GENERIC_VERSION) >> EF_AMDGPU_GENERIC_VERSION_OFFSET) : 0;
}
bool CodeObject::isGenericTarget(const void* image) {
return getGenericVersion(image) >= EF_AMDGPU_GENERIC_VERSION_MIN;
}
bool CodeObject::containGenericTarget(const void *data) {
const auto obheader = reinterpret_cast<const __ClangOffloadBundleUncompressedHeader*>(data);
const auto* desc = &obheader->desc[0];
for (uint64_t i = 0; i < obheader->numOfCodeObjects; ++i,
desc = reinterpret_cast<const __ClangOffloadBundleInfo*>(
reinterpret_cast<uintptr_t>(&desc->bundleEntryId[0]) + desc->bundleEntryIdSize)) {
if (desc->size == 0) continue;
const void* image =
reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(obheader) + desc->offset);
if (isGenericTarget(image)) {
return true;
}
}
return false;
}
uint64_t CodeObject::ElfSize(const void* emi) { return amd::Elf::getElfSize(emi); }
// Consumes the string 'consume_' from the starting of the given input
// eg: input = amdgcn-amd-amdhsa--gfx908 and consume_ is amdgcn-amd-amdhsa--
// input will become gfx908.
static bool consume(std::string& input, std::string consume_) {
if (input.substr(0, consume_.size()) != consume_) {
return false;
}
input = input.substr(consume_.size());
return true;
}
// Trim String till character, will be used to get gpuname
// example: input is gfx908:sram-ecc+ and trim char is :
// input will become :sram-ecc+.
static std::string trimName(std::string& input, char trim) {
auto pos_ = input.find(trim);
auto res = input;
if (pos_ == std::string::npos) {
input = "";
} else {
res = input.substr(0, pos_);
input = input.substr(pos_);
}
return res;
}
// Trim String till character, will be used to get bundle entry ID.
// example: input is amdgcn-amd-amdhsa--gfx1035.bc and trim char is .
// input will become amdgcn-amd-amdhsa--gfx1035
static bool trimNameTail(std::string& input, char trim) {
auto pos_ = input.rfind(trim);
if (pos_ == std::string::npos) {
return false;
}
input = input.substr(0, pos_);
return true;
}
static char getFeatureValue(std::string& input, std::string feature) {
char res = ' ';
if (consume(input, std::move(feature))) {
res = input[0];
input = input.substr(1);
}
return res;
}
static bool getTargetIDValue(std::string& input, std::string& processor, char& sramecc_value,
char& xnack_value) {
processor = trimName(input, ':');
sramecc_value = getFeatureValue(input, std::string(":sramecc"));
if (sramecc_value != ' ' && sramecc_value != '+' && sramecc_value != '-') return false;
xnack_value = getFeatureValue(input, std::string(":xnack"));
if (xnack_value != ' ' && xnack_value != '+' && xnack_value != '-') return false;
return true;
}
static bool isCodeObjectCompatibleWithDevice(std::string co_triple_target_id,
std::string agent_triple_target_id, unsigned int genericVersion) {
// Primitive Check
if (co_triple_target_id == agent_triple_target_id) return true;
// Parse code object triple target id
if (!consume(co_triple_target_id, std::string(kAmdgcnTargetTriple) + '-')) {
return false;
}
std::string co_processor;
char co_sram_ecc, co_xnack;
if (!getTargetIDValue(co_triple_target_id, co_processor, co_sram_ecc, co_xnack)) {
return false;
}
if (!co_triple_target_id.empty()) return false;
// Parse agent isa triple target id
if (!consume(agent_triple_target_id, std::string(kAmdgcnTargetTriple) + '-')) {
return false;
}
std::string agent_isa_processor;
char isa_sram_ecc, isa_xnack;
if (!getTargetIDValue(agent_triple_target_id, agent_isa_processor, isa_sram_ecc, isa_xnack)) {
return false;
}
if (!agent_triple_target_id.empty()) return false;
// Check for compatibility
if (genericVersion >= EF_AMDGPU_GENERIC_VERSION_MIN) {
// co_processor is generic target
if (!helpers::IsCompatibleWithGenericTarget(co_processor, agent_isa_processor))
return false;
} else if (agent_isa_processor != co_processor) {
return false;
}
if (co_sram_ecc != ' ') {
if (co_sram_ecc != isa_sram_ecc) return false;
}
if (co_xnack != ' ') {
if (co_xnack != isa_xnack) return false;
}
return true;
}
bool CodeObject::QueryGenericTarget(std::string agentTarget, std::string& processor,
char& sram_ecc, char& xnack) {
static const std::string head = std::string(kAmdgcnTargetTriple) + '-';
// Parse agent isa triple target id
if (!consume(agentTarget, head)) {
return false;
}
if (!getTargetIDValue(agentTarget, processor, sram_ecc, xnack)) {
return false;
}
if (processor.empty()) return false;
auto &map = helpers::GenericTargetMapping();
auto search = map.find(processor);
if (search == map.end()) return false;
processor = head + search->second;
return true;
}
// ================================================================================================
size_t CodeObject::getFatbinSize(const void* data, const bool isCompressed) {
if (isCompressed) {
const auto obheader = reinterpret_cast<const __ClangOffloadBundleCompressedHeader*>(data);
return obheader->totalSize;
} else {
const auto obheader = reinterpret_cast<const __ClangOffloadBundleUncompressedHeader*>(data);
const __ClangOffloadBundleInfo* desc = &obheader->desc[0];
uint64_t i = 0;
while (++i < obheader->numOfCodeObjects) {
desc = reinterpret_cast<const __ClangOffloadBundleInfo*>(
reinterpret_cast<uintptr_t>(&desc->bundleEntryId[0]) + desc->bundleEntryIdSize);
}
return desc->offset + desc->size;
}
}
// ================================================================================================
hipError_t CodeObject::extractCodeObjectFromFatBinaryUsingComgr(
const void* data, size_t size, const std::vector<std::string>& agent_triple_target_ids,
std::vector<std::pair<const void*, size_t>>& code_objs) {
hipError_t hipStatus = hipSuccess;
amd_comgr_status_t comgrStatus = AMD_COMGR_STATUS_SUCCESS;
const size_t num_devices = agent_triple_target_ids.size();
size_t num_code_objs = num_devices;
bool isCompressed = false;
if (!IsClangOffloadMagicBundle(data, isCompressed)) {
ClPrint(amd::LOG_INFO, amd::LOG_COMGR, "IsClangOffloadMagicBundle(%p) return false", data);
// hipModuleLoadData() will possibly call here
return hipErrorInvalidKernelFile;
}
if (size == 0) size = getFatbinSize(data, isCompressed);
amd_comgr_data_t dataCodeObj{0};
amd_comgr_data_set_t dataSetBundled{0};
amd_comgr_data_set_t dataSetUnbundled{0};
amd_comgr_action_info_t actionInfoUnbundle{0};
amd_comgr_data_t item{0};
std::set<std::string> devicesSet{}; // To make sure device is unique
std::set<std::string> genericDevicesSet{}; // Used to record generic targets
std::vector<const char*> bundleEntryIDs{};
static const std::string hipv4 = kOffloadKindHipv4_; // bundled code objects need the prefix
for (size_t i = 0; i < num_devices; i++) {
auto res = devicesSet.insert(hipv4 + agent_triple_target_ids[i]);
if (res.second) {
// This is a new device in devicesSet
bundleEntryIDs.push_back(res.first->c_str());
std::string processor;
char sram_ecc = ' ', xnack = ' ';
if (!QueryGenericTarget(agent_triple_target_ids[i], processor, sram_ecc, xnack)) {
continue; // No generic target for this device
}
// Now processor is generic such as
// amdgcn-amd-amdhsa--gfx9-4-generic, amdgcn-amd-amdhsa--gfx11-generic
processor = hipv4 + processor;
auto ret = genericDevicesSet.insert(processor);
if (ret.second) {
// Without feature
bundleEntryIDs.push_back(ret.first->c_str());
}
if (xnack != ' ') {
ret = genericDevicesSet.insert(processor + ":xnack" + xnack);
if (ret.second) {
// Generic target with xnack feature
bundleEntryIDs.push_back(ret.first->c_str());
}
}
if (sram_ecc != ' ') {
processor += ":sramecc";
processor += sram_ecc;
ret = genericDevicesSet.insert(processor);
if (ret.second) {
// Generic target with sramecc feature
bundleEntryIDs.push_back(ret.first->c_str());
}
if (xnack != ' ') {
ret = genericDevicesSet.insert(processor + ":xnack" + xnack);
if (ret.second) {
// Generic target with sramecc and xnack features
bundleEntryIDs.push_back(ret.first->c_str());
}
}
}
}
}
do {
// Create Bundled dataset
comgrStatus = amd::Comgr::create_data_set(&dataSetBundled);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::create_data_set() failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
// CodeObject
comgrStatus = amd::Comgr::create_data(AMD_COMGR_DATA_KIND_OBJ_BUNDLE, &dataCodeObj);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError(
"amd::Comgr::create_data(AMD_COMGR_DATA_KIND_OBJ_BUNDLE) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::set_data(dataCodeObj, size, static_cast<const char*>(data));
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::set_data(size=%zu, data=%p) failed with status 0x%xh", size, data,
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::set_data_name(dataCodeObj, kHipFatBinName);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError(
"amd::Comgr::set_data_name("
") failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::data_set_add(dataSetBundled, dataCodeObj);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::data_set_add() failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
// Set up ActionInfo
comgrStatus = amd::Comgr::create_action_info(&actionInfoUnbundle);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::create_action_info() failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::action_info_set_language(actionInfoUnbundle, AMD_COMGR_LANGUAGE_HIP);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::action_info_set_language(HIP) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::action_info_set_bundle_entry_ids(
actionInfoUnbundle, bundleEntryIDs.data(), bundleEntryIDs.size());
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError(
"amd::Comgr::action_info_set_bundle_entry_ids(%p, %zu) failed with status 0x%xh",
bundleEntryIDs.data(), bundleEntryIDs.size(), comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
// Unbundle
comgrStatus = amd::Comgr::create_data_set(&dataSetUnbundled);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::create_data_set(&dataSetUnbundled) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::do_action(AMD_COMGR_ACTION_UNBUNDLE, actionInfoUnbundle,
dataSetBundled, dataSetUnbundled);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::do_action(AMD_COMGR_ACTION_UNBUNDLE) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
// Check CodeObject count
size_t count = 0;
comgrStatus =
amd::Comgr::action_data_count(dataSetUnbundled, AMD_COMGR_DATA_KIND_EXECUTABLE, &count);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::action_data_count() failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
// Initialize Code objects
code_objs.reserve(num_code_objs);
for (size_t i = 0; i < num_code_objs; i++) {
code_objs.push_back(std::make_pair(nullptr, 0));
}
for (size_t i = 0; i < count; i++) {
if (num_code_objs == 0) break;
size_t itemSize = 0;
comgrStatus = amd::Comgr::action_data_get_data(dataSetUnbundled,
AMD_COMGR_DATA_KIND_EXECUTABLE, i, &item);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::action_data_get_data(%zu/%zu) failed with 0x%xh", i, count,
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
comgrStatus = amd::Comgr::get_data_name(item, &itemSize, nullptr);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::get_data_name(%zu/%zu) failed with 0x%xh", i, count,
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
std::string bundleEntryId(itemSize, 0);
comgrStatus = amd::Comgr::get_data_name(item, &itemSize, bundleEntryId.data());
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::get_data_name(%zu/%zu, %d) failed with 0x%xh", i, count,
itemSize, comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
ClPrint(amd::LOG_DEBUG, amd::LOG_COMGR, "Found bundleEntryId=%s", bundleEntryId.c_str());
// Remove bundleEntryId_
if (!consume(bundleEntryId, kOffloadHipV4FatBinName_)) {
// This is behavour in comgr unbundling which is subject to change.
// So just give info.
ClPrint(amd::LOG_INFO, amd::LOG_COMGR,
"bundleEntryId=%s isn't prefixed with %s", bundleEntryId.c_str(),
kOffloadHipV4FatBinName_);
}
trimNameTail(bundleEntryId, '.'); // Remove .fileExtention
// Currently we only support EF_AMDGPU_GENERIC_VERSION_MIN on generic target
uint32_t genericVersion =
bundleEntryId.find("generic") != bundleEntryId.npos ? EF_AMDGPU_GENERIC_VERSION_MIN : 0;
char* itemData = nullptr;
for (size_t dev = 0; dev < num_devices; ++dev) {
if (code_objs[dev].first != nullptr) {
if (!isGenericTarget(code_objs[dev].first)) {
continue; // Specific target already found
} else if (genericVersion >= EF_AMDGPU_GENERIC_VERSION_MIN) {
continue; // Generic target already found, no need to check another generic
}
}
ClPrint(amd::LOG_DEBUG, amd::LOG_COMGR, "agent_triple_target_ids[%zu]=%s, bundleEntryId=%s",
dev, agent_triple_target_ids[dev].c_str(), bundleEntryId.c_str());
if (isCodeObjectCompatibleWithDevice(bundleEntryId, agent_triple_target_ids[dev],
genericVersion)) {
if (itemData == nullptr) {
itemSize = 0;
comgrStatus = amd::Comgr::get_data(item, &itemSize, nullptr);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::get_data(%zu/%zu) failed with 0x%xh", i, count,
comgrStatus);
hipStatus = hipErrorInvalidValue;
break;
}
if (itemSize == 0) {
// If there isn't a code object for this device,
// amd::Comgr::do_action(AMD_COMGR_ACTION_UNBUNDLE) still returns item with
// valid name but no data. We need continue searching for other devices
ClPrint(amd::LOG_INFO, amd::LOG_COMGR,
"amd::Comgr::get_data() return 0 size for agent_triple_target_ids[%zu]=%s", dev,
agent_triple_target_ids[dev].c_str());
break;
}
// itemData should be deleted in fatbin's destructor
itemData = new char[itemSize];
if (itemData == nullptr) {
LogError("no enough memory");
hipStatus = hipErrorOutOfMemory;
break;
}
comgrStatus = amd::Comgr::get_data(item, &itemSize, itemData);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::get_data(%zu/%zu, %d) failed with 0x%xh", i, count,
itemSize, comgrStatus);
hipStatus = hipErrorInvalidValue;
delete[] itemData;
itemData = nullptr;
break;
}
}
if (code_objs[dev].first != nullptr) {
// This must be data of generic target
bool used = false; // Still used by other devices?
for (size_t i = 0; i < num_devices; ++i) {
if (dev != i && code_objs[dev].first == code_objs[i].first) {
used = true;
break;
}
}
if (!used) {
delete[] reinterpret_cast<const char*>(code_objs[dev].first);
}
} else {
--num_code_objs;
}
code_objs[dev] = std::make_pair(reinterpret_cast<const void*>(itemData), itemSize);
ClPrint(amd::LOG_DEBUG, amd::LOG_COMGR,
"Found agent_triple_target_ids[%zu]=%s: item: Data=%p(%s, %s), "
"Size=%zu, num_code_objs=%zu",
dev, agent_triple_target_ids[dev].c_str(), itemData,
isCompressed ? "compressed" : "uncompressed",
genericVersion >= EF_AMDGPU_GENERIC_VERSION_MIN ? "generic" : "non-generic",
itemSize, num_code_objs);
}
}
comgrStatus = amd::Comgr::release_data(item);
item.handle = 0;
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::release_data(item) failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
}
if (hipStatus != hipSuccess) break;
}
} while (0);
// Cleanup
if (actionInfoUnbundle.handle) {
comgrStatus = amd::Comgr::destroy_action_info(actionInfoUnbundle);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::destroy_action_info(actionInfoUnbundle) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
}
}
if (dataSetBundled.handle) {
comgrStatus = amd::Comgr::destroy_data_set(dataSetBundled);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::destroy_data_set(dataSetBundled) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
}
}
if (dataSetUnbundled.handle) {
comgrStatus = amd::Comgr::destroy_data_set(dataSetUnbundled);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::destroy_data_set(dataSetUnbundled) failed with status 0x%xh",
comgrStatus);
hipStatus = hipErrorInvalidValue;
}
}
if (dataCodeObj.handle) {
comgrStatus = amd::Comgr::release_data(dataCodeObj);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::release_data(dataCodeObj) failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
}
}
if (item.handle) {
comgrStatus = amd::Comgr::release_data(item);
if (comgrStatus != AMD_COMGR_STATUS_SUCCESS) {
LogPrintfError("amd::Comgr::release_data(item) failed with status 0x%xh", comgrStatus);
hipStatus = hipErrorInvalidValue;
}
}
return hipStatus;
}
hipError_t DynCO::loadCodeObject(const char* fname, const void* image) {
amd::ScopedLock lock(dclock_);
@@ -620,7 +42,7 @@ hipError_t DynCO::loadCodeObject(const char* fname, const void* image) {
// Number of devices = 1 in dynamic code object
fb_info_ = new FatBinaryInfo(fname, image);
std::vector<hip::Device*> devices = {g_devices[ihipGetDevice()]};
IHIP_RETURN_ONFAIL(fb_info_->ExtractFatBinary(devices));
IHIP_RETURN_ONFAIL(fb_info_->ExtractFatBinaryUsingCOMGR(devices));
// No Lazy loading for DynCO
IHIP_RETURN_ONFAIL(fb_info_->BuildProgram(ihipGetDevice()));
@@ -834,7 +256,7 @@ hipError_t StatCO::digestFatBinary(const void* data, FatBinaryInfo*& programs) {
// Create a new fat binary object and extract the fat binary for all devices.
FatBinaryInfo* fatBinaryInfo = new FatBinaryInfo(nullptr, data);
hipError_t err = fatBinaryInfo->ExtractFatBinary(g_devices);
hipError_t err = fatBinaryInfo->ExtractFatBinaryUsingCOMGR(g_devices);
programs = fatBinaryInfo;
return err;
}