Remapper: remove debug info for IDs stripped in other passes
If some DCE is performed such as removing dead functions, then even if we are NOT stripping debug info, we still must remove the debug opcodes that refer to the now-dead IDs. Also, this adds a small change to perform no ID remapping if none is requested, making spirv-remap properly be a no-op if no options are given.
This commit is contained in:
parent
906cc21816
commit
297754cfe8
11 changed files with 246 additions and 219 deletions
|
|
@ -327,12 +327,10 @@ namespace spv {
|
|||
bound(maxBound); // reset header ID bound to as big as it now needs to be
|
||||
}
|
||||
|
||||
// Mark debug instructions for stripping
|
||||
void spirvbin_t::stripDebug()
|
||||
{
|
||||
if ((options & STRIP) == 0)
|
||||
return;
|
||||
|
||||
// build local Id and name maps
|
||||
// Strip instructions in the stripOp set: debug info.
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// remember opcodes we want to strip later
|
||||
|
|
@ -343,6 +341,32 @@ namespace spv {
|
|||
op_fn_nop);
|
||||
}
|
||||
|
||||
// Mark instructions that refer to now-removed IDs for stripping
|
||||
void spirvbin_t::stripDeadRefs()
|
||||
{
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// strip opcodes pointing to removed data
|
||||
switch (opCode) {
|
||||
case spv::OpName:
|
||||
case spv::OpMemberName:
|
||||
case spv::OpDecorate:
|
||||
case spv::OpMemberDecorate:
|
||||
if (idPosR.find(asId(start+1)) == idPosR.end())
|
||||
stripInst(start);
|
||||
break;
|
||||
default:
|
||||
break; // leave it alone
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
op_fn_nop);
|
||||
|
||||
strip();
|
||||
}
|
||||
|
||||
// Update local maps of ID, type, etc positions
|
||||
void spirvbin_t::buildLocalMaps()
|
||||
{
|
||||
msg(2, 2, std::string("build local maps: "));
|
||||
|
|
@ -351,7 +375,6 @@ namespace spv {
|
|||
idMapL.clear();
|
||||
// preserve nameMap, so we don't clear that.
|
||||
fnPos.clear();
|
||||
fnPosDCE.clear();
|
||||
fnCalls.clear();
|
||||
typeConstPos.clear();
|
||||
idPosR.clear();
|
||||
|
|
@ -366,10 +389,6 @@ namespace spv {
|
|||
// build local Id and name maps
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// remember opcodes we want to strip later
|
||||
if ((options & STRIP) && isStripOp(opCode))
|
||||
stripInst(start);
|
||||
|
||||
unsigned word = start+1;
|
||||
spv::Id typeId = spv::NoResult;
|
||||
|
||||
|
|
@ -957,7 +976,6 @@ namespace spv {
|
|||
if (call_it == fnCalls.end() || call_it->second == 0) {
|
||||
changed = true;
|
||||
stripRange.push_back(fn->second);
|
||||
fnPosDCE.insert(*fn);
|
||||
|
||||
// decrease counts of called functions
|
||||
process(
|
||||
|
|
@ -1011,11 +1029,15 @@ namespace spv {
|
|||
// Remove single-use function variables + associated decorations and names
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
if ((opCode == spv::OpVariable && varUseCount[asId(start+2)] == 1) ||
|
||||
(opCode == spv::OpDecorate && varUseCount[asId(start+1)] == 1) ||
|
||||
(opCode == spv::OpName && varUseCount[asId(start+1)] == 1)) {
|
||||
stripInst(start);
|
||||
}
|
||||
spv::Id id = spv::NoResult;
|
||||
if (opCode == spv::OpVariable)
|
||||
id = asId(start+2);
|
||||
if (opCode == spv::OpDecorate || opCode == spv::OpName)
|
||||
id = asId(start+1);
|
||||
|
||||
if (id != spv::NoResult && varUseCount[id] == 1)
|
||||
stripInst(start);
|
||||
|
||||
return true;
|
||||
},
|
||||
op_fn_nop);
|
||||
|
|
@ -1276,25 +1298,31 @@ namespace spv {
|
|||
// Set up opcode tables from SpvDoc
|
||||
spv::Parameterize();
|
||||
|
||||
validate(); // validate header
|
||||
buildLocalMaps();
|
||||
validate(); // validate header
|
||||
buildLocalMaps(); // build ID maps
|
||||
|
||||
msg(3, 4, std::string("ID bound: ") + std::to_string(bound()));
|
||||
|
||||
if (options & STRIP) stripDebug();
|
||||
strip(); // strip out data we decided to eliminate
|
||||
if (options & OPT_LOADSTORE) optLoadStore();
|
||||
if (options & OPT_FWD_LS) forwardLoadStores();
|
||||
if (options & DCE_FUNCS) dceFuncs();
|
||||
if (options & DCE_VARS) dceVars();
|
||||
if (options & DCE_TYPES) dceTypes();
|
||||
strip(); // strip out data we decided to eliminate
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
stripDeadRefs(); // remove references to things we DCEed
|
||||
// after the last strip, we must clean any debug info referring to now-deleted data
|
||||
|
||||
if (options & MAP_TYPES) mapTypeConst();
|
||||
if (options & MAP_NAMES) mapNames();
|
||||
if (options & MAP_FUNCS) mapFnBodies();
|
||||
|
||||
mapRemainder(); // map any unmapped IDs
|
||||
applyMap(); // Now remap each shader to the new IDs we've come up with
|
||||
if (options & MAP_ALL) {
|
||||
mapRemainder(); // map any unmapped IDs
|
||||
applyMap(); // Now remap each shader to the new IDs we've come up with
|
||||
}
|
||||
}
|
||||
|
||||
// remap from a memory image
|
||||
|
|
|
|||
|
|
@ -239,7 +239,8 @@ private:
|
|||
|
||||
void applyMap(); // remap per local name map
|
||||
void mapRemainder(); // map any IDs we haven't touched yet
|
||||
void stripDebug(); // strip debug info
|
||||
void stripDebug(); // strip all debug info
|
||||
void stripDeadRefs(); // strips debug info for now-dead references after DCE
|
||||
void strip(); // remove debug symbols
|
||||
|
||||
std::vector<spirword_t> spv; // SPIR words
|
||||
|
|
@ -264,7 +265,6 @@ private:
|
|||
// Function start and end. use unordered_map because we'll have
|
||||
// many fewer functions than IDs.
|
||||
std::unordered_map<spv::Id, range_t> fnPos;
|
||||
std::unordered_map<spv::Id, range_t> fnPosDCE; // deleted functions
|
||||
|
||||
// Which functions are called, anywhere in the module, with a call count
|
||||
std::unordered_map<spv::Id, int> fnCalls;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue