DirectXShaderCompiler/lib/HLSL/DxilDeleteRedundantDebugVal...

135 строки
4.1 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// //
// DxilDeleteRedundantDebugValues.cpp //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
///////////////////////////////////////////////////////////////////////////////
//
// Removes as many dbg.value's as possible:
//
// 1. Search for all scopes (and their parent scopes) that have any real
// (non-debug)
// instructions at all.
//
// 2. For each dbg.value, if it's refering to a variable from a scope not in
// the set of scopes from step 1, then delete it.
//
// 3. In any contiguous series of dbg.value instructions, if there are
// dbg.value's
// that point to the same variable+fragment, then delete all but the last
// one, since it would be the only authentic mapping for that variable
// fragment.
#include "dxc/HLSL/DxilGenerationPass.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include <unordered_set>
using namespace llvm;
namespace {
class DxilDeleteRedundantDebugValues : public ModulePass {
public:
static char ID;
explicit DxilDeleteRedundantDebugValues() : ModulePass(ID) {
initializeDxilDeleteRedundantDebugValuesPass(
*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override;
};
char DxilDeleteRedundantDebugValues::ID;
} // namespace
bool DxilDeleteRedundantDebugValues::runOnModule(Module &M) {
if (!llvm::hasDebugInfo(M))
return false;
bool Changed = false;
std::unordered_set<DILocalScope *> SeenScopes;
typedef std::pair<DILocalVariable *, DIExpression *> VarPair;
SmallDenseMap<VarPair, DbgValueInst *> SeenVar;
for (Function &F : M) {
SeenScopes.clear();
SeenVar.clear();
// Collect a set of all scopes that are attached to non-debug instructions
// There's no need to keep debug info for any variables in any scopes that
// don't have any real instructions anyway.
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
if (isa<DbgInfoIntrinsic>(I))
continue;
DebugLoc DL = I.getDebugLoc();
if (!DL)
continue;
DILocalScope *Scope = cast_or_null<DILocalScope>(DL.getScope());
if (!Scope)
continue;
while (Scope) {
SeenScopes.insert(Scope);
if (DILexicalBlockBase *LB = dyn_cast<DILexicalBlockBase>(Scope)) {
Scope = LB->getScope();
} else {
Scope = nullptr;
}
}
}
}
for (BasicBlock &BB : F) {
for (auto it = BB.begin(), end = BB.end(); it != end;) {
Instruction &I = *(it++);
if (!isa<DbgInfoIntrinsic>(I)) {
SeenVar.clear();
continue;
}
DbgValueInst *DI = dyn_cast<DbgValueInst>(&I);
if (!DI)
continue;
DILocalVariable *Var = DI->getVariable();
DIExpression *Expr = DI->getExpression();
VarPair Pair = VarPair(Var, Expr);
if (!SeenScopes.count(Var->getScope())) {
Changed = true;
DI->eraseFromParent();
continue;
}
auto findIt = SeenVar.find(Pair);
if (findIt != SeenVar.end()) {
findIt->second->eraseFromParent();
findIt->second = DI;
Changed = true;
} else {
SeenVar[Pair] = DI;
}
}
}
}
return Changed;
}
ModulePass *llvm::createDxilDeleteRedundantDebugValuesPass() {
return new DxilDeleteRedundantDebugValues();
}
INITIALIZE_PASS(DxilDeleteRedundantDebugValues,
"dxil-delete-redundant-debug-values",
"Dxil Delete Redundant Debug Values", false, false)