1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2017-2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "Compiler/MetaDataApi/PurgeMetaDataUtils.hpp"
#include "Compiler/IGCPassSupport.h"
#include "Compiler/CodeGenPublic.h"
using namespace llvm;
using namespace IGC;
// Register pass to igc-opt
#define PASS_FLAG "igc-purgeMetaDataUtils-import"
#define PASS_DESCRIPTION "PurgeMetaDataUtilsImport"
#define PASS_CFG_ONLY false
#define PASS_ANALYSIS false
IGC_INITIALIZE_PASS_BEGIN(PurgeMetaDataUtils, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
IGC_INITIALIZE_PASS_DEPENDENCY(MetaDataUtilsWrapper)
IGC_INITIALIZE_PASS_DEPENDENCY(CodeGenContextWrapper)
IGC_INITIALIZE_PASS_END(PurgeMetaDataUtils, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
char PurgeMetaDataUtils::ID = 0;
PurgeMetaDataUtils::PurgeMetaDataUtils() : ModulePass(ID) {
initializePurgeMetaDataUtilsPass(*PassRegistry::getPassRegistry());
}
// Remove metadata entries in metadata utils for inlined or dead functions.
// TODO: get rid of this step if we do not keep any non-kernel function in the
// metadata util object.
bool PurgeMetaDataUtils::runOnModule(Module &M) { return purgeMetaDataUtils(M, &getAnalysis<MetaDataUtilsWrapper>()); }
bool IGC::purgeMetaDataUtils(Module &M, MetaDataUtilsWrapper *MDUW) {
IGCMD::MetaDataUtils *MDUtils = MDUW->getMetaDataUtils();
auto shouldRemoveFunction = [=](llvm::Module &M, void *ptr) {
llvm::Function *F = nullptr;
// Function may have been removed already.
for (auto &G : M.getFunctionList()) {
if (&G == ptr) {
F = &G;
break;
}
}
// Already deleted, or not used non-kernels.
if (F == nullptr) {
return true;
}
if (F->use_empty() && !isEntryFunc(MDUtils, F)) {
if (F->hasFnAttribute("referenced-indirectly") && GlobalValue::isExternalLinkage(F->getLinkage())) {
// Do not delete externally linked functions, even if there are no uses in the current module.
// However if it's only used internally, and we somehow resolve the indirect call, we can remove it.
return false;
}
if (isPixelShaderPhaseFunction(F)) {
// In some cases pixel shader codegen splits the compilation
// to phases, removing entry functions from metadata, but assumes they
// will be available in the next pass. Leave such functions in the module.
return false;
}
if (IGC_IS_FLAG_ENABLED(EnableUnmaskedFunctions) && F->hasFnAttribute("sycl-unmasked"))
return false;
F->eraseFromParent();
return true;
}
// Kernels or used non-kernels.
return false;
};
// Collect all functions for which metadata will be removed.
SmallSet<llvm::Function *, 8> ToBeDeleted;
auto checkFuncRange = [&](auto beginIt, auto endIt) {
for (auto it = beginIt, e = endIt; it != e; ++it) {
if (shouldRemoveFunction(M, it->first)) {
ToBeDeleted.insert(it->first);
}
}
};
auto &FuncMD = MDUW->getModuleMetaData()->FuncMD;
checkFuncRange(MDUtils->begin_FunctionsInfo(), MDUtils->end_FunctionsInfo());
checkFuncRange(FuncMD.begin(), FuncMD.end());
// Remove them.
for (auto F : ToBeDeleted) {
auto Iter = MDUtils->findFunctionsInfoItem(F);
if (Iter != MDUtils->end_FunctionsInfo()) {
MDUtils->eraseFunctionsInfoItem(Iter);
}
if (FuncMD.find(F) != FuncMD.end()) {
FuncMD.erase(F);
}
}
// Update when there is any change.
if (!ToBeDeleted.empty()) {
MDUtils->save(M.getContext());
}
return !ToBeDeleted.empty();
}
|