Merged PR 32: Remove unused debug info when linking.
Remove unused debug info when linking.
This commit is contained in:
Родитель
88de36b2f5
Коммит
be06ec1d3a
|
@ -31,6 +31,7 @@
|
||||||
#include "dxc/HLSL/DxilContainer.h"
|
#include "dxc/HLSL/DxilContainer.h"
|
||||||
#include "llvm/IR/DiagnosticPrinter.h"
|
#include "llvm/IR/DiagnosticPrinter.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
|
#include "llvm/IR/DebugInfo.h"
|
||||||
|
|
||||||
#include "dxc/HLSL/DxilGenerationPass.h"
|
#include "dxc/HLSL/DxilGenerationPass.h"
|
||||||
#include "llvm/IR/LegacyPassManager.h"
|
#include "llvm/IR/LegacyPassManager.h"
|
||||||
|
@ -325,6 +326,7 @@ struct DxilLinkJob {
|
||||||
Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
|
||||||
const ShaderModel *pSM);
|
const ShaderModel *pSM);
|
||||||
std::unique_ptr<llvm::Module> LinkToLib(const ShaderModel *pSM);
|
std::unique_ptr<llvm::Module> LinkToLib(const ShaderModel *pSM);
|
||||||
|
void StripDeadDebugInfo(llvm::Module &M);
|
||||||
void RunPreparePass(llvm::Module &M);
|
void RunPreparePass(llvm::Module &M);
|
||||||
void AddFunction(std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair);
|
void AddFunction(std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair);
|
||||||
void AddFunction(llvm::Function *F);
|
void AddFunction(llvm::Function *F);
|
||||||
|
@ -878,9 +880,87 @@ void DxilLinkJob::AddFunction(llvm::Function *F) {
|
||||||
m_functionDecls[F->getName()] = F;
|
m_functionDecls[F->getName()] = F;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DxilLinkJob::RunPreparePass(Module &M) {
|
// Clone of StripDeadDebugInfo::runOnModule.
|
||||||
legacy::PassManager PM;
|
// Also remove function which not not in current Module.
|
||||||
|
void DxilLinkJob::StripDeadDebugInfo(Module &M) {
|
||||||
|
LLVMContext &C = M.getContext();
|
||||||
|
// Find all debug info in F. This is actually overkill in terms of what we
|
||||||
|
// want to do, but we want to try and be as resilient as possible in the face
|
||||||
|
// of potential debug info changes by using the formal interfaces given to us
|
||||||
|
// as much as possible.
|
||||||
|
DebugInfoFinder F;
|
||||||
|
F.processModule(M);
|
||||||
|
|
||||||
|
// For each compile unit, find the live set of global variables/functions and
|
||||||
|
// replace the current list of potentially dead global variables/functions
|
||||||
|
// with the live list.
|
||||||
|
SmallVector<Metadata *, 64> LiveGlobalVariables;
|
||||||
|
SmallVector<Metadata *, 64> LiveSubprograms;
|
||||||
|
DenseSet<const MDNode *> VisitedSet;
|
||||||
|
|
||||||
|
for (DICompileUnit *DIC : F.compile_units()) {
|
||||||
|
// Create our live subprogram list.
|
||||||
|
bool SubprogramChange = false;
|
||||||
|
for (DISubprogram *DISP : DIC->getSubprograms()) {
|
||||||
|
// Make sure we visit each subprogram only once.
|
||||||
|
if (!VisitedSet.insert(DISP).second)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If the function referenced by DISP is not null, the function is live.
|
||||||
|
if (Function *Func = DISP->getFunction()) {
|
||||||
|
if (Func->getParent() == &M)
|
||||||
|
LiveSubprograms.push_back(DISP);
|
||||||
|
else
|
||||||
|
SubprogramChange = true;
|
||||||
|
} else {
|
||||||
|
SubprogramChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create our live global variable list.
|
||||||
|
bool GlobalVariableChange = false;
|
||||||
|
for (DIGlobalVariable *DIG : DIC->getGlobalVariables()) {
|
||||||
|
// Make sure we only visit each global variable only once.
|
||||||
|
if (!VisitedSet.insert(DIG).second)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If the global variable referenced by DIG is not null, the global
|
||||||
|
// variable is live.
|
||||||
|
if (Constant *CV = DIG->getVariable()) {
|
||||||
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(CV)) {
|
||||||
|
if (GV->getParent() == &M) {
|
||||||
|
LiveGlobalVariables.push_back(DIG);
|
||||||
|
} else {
|
||||||
|
GlobalVariableChange = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LiveGlobalVariables.push_back(DIG);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GlobalVariableChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found dead subprograms or global variables, replace the current
|
||||||
|
// subprogram list/global variable list with our new live subprogram/global
|
||||||
|
// variable list.
|
||||||
|
if (SubprogramChange) {
|
||||||
|
DIC->replaceSubprograms(MDTuple::get(C, LiveSubprograms));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GlobalVariableChange) {
|
||||||
|
DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset lists for the next iteration.
|
||||||
|
LiveSubprograms.clear();
|
||||||
|
LiveGlobalVariables.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DxilLinkJob::RunPreparePass(Module &M) {
|
||||||
|
StripDeadDebugInfo(M);
|
||||||
|
legacy::PassManager PM;
|
||||||
PM.add(createAlwaysInlinerPass(/*InsertLifeTime*/ false));
|
PM.add(createAlwaysInlinerPass(/*InsertLifeTime*/ false));
|
||||||
|
|
||||||
// Remove unused functions.
|
// Remove unused functions.
|
||||||
|
|
|
@ -181,9 +181,10 @@ TEST_F(LinkerTest, RunLinkAllProfiles) {
|
||||||
CreateLinker(&pLinker);
|
CreateLinker(&pLinker);
|
||||||
|
|
||||||
LPCWSTR libName = L"entry";
|
LPCWSTR libName = L"entry";
|
||||||
|
LPCWSTR option[] = { L"-Zi" };
|
||||||
|
|
||||||
CComPtr<IDxcBlob> pEntryLib;
|
CComPtr<IDxcBlob> pEntryLib;
|
||||||
CompileLib(L"..\\CodeGenHLSL\\lib_entries2.hlsl", &pEntryLib);
|
CompileLib(L"..\\CodeGenHLSL\\lib_entries2.hlsl", &pEntryLib, option, 1);
|
||||||
RegisterDxcModule(libName, pEntryLib, pLinker);
|
RegisterDxcModule(libName, pEntryLib, pLinker);
|
||||||
|
|
||||||
Link(L"vs_main", L"vs_6_0", pLinker, {libName}, {},{});
|
Link(L"vs_main", L"vs_6_0", pLinker, {libName}, {},{});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче