diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 1a8ba449..8c1c84f9 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -719,6 +719,7 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector& out) for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) entryPoint->addIdOperand(*it); + builder.eliminateDeadDecorations(); builder.dump(out); } diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index d7f6fc7b..158c86b9 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -2130,6 +2130,35 @@ Id Builder::accessChainGetInferredType() return type; } +// comment in header +void Builder::eliminateDeadDecorations() { + std::unordered_set reachable_blocks; + std::unordered_set unreachable_definitions; + // Collect IDs defined in unreachable blocks. For each function, label the + // reachable blocks first. Then for each unreachable block, collect the + // result IDs of the instructions in it. + for (auto& f : module.getFunctions()) { + Block* entry = f->getEntryBlock(); + inReadableOrder(entry, [&reachable_blocks](const Block* b) { + reachable_blocks.insert(b); + }); + for (auto& b : f->getBlocks()) { + if (!reachable_blocks.count(b)) { + for (auto& i : b->getInstructions()) { + unreachable_definitions.insert(i->getResultId()); + } + } + } + } + decorations.erase(std::remove_if(decorations.begin(), decorations.end(), + [&unreachable_definitions](std::unique_ptr& I) { + Instruction* inst = I.get(); + Id decoration_id = inst->getIdOperand(0); + return unreachable_definitions.count(decoration_id) != 0; + }), + decorations.end()); +} + void Builder::dump(std::vector& out) const { // Header, before first instructions: diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index d6dc6121..e16ba38c 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -512,6 +512,9 @@ public: // based on the type of the base and the chain of dereferences. Id accessChainGetInferredType(); + // Remove OpDecorate instructions whose operands are defined in unreachable + // blocks. + void eliminateDeadDecorations(); void dump(std::vector&) const; void createBranch(Block* block); diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h index 98f4971b..3c483872 100755 --- a/SPIRV/spvIR.h +++ b/SPIRV/spvIR.h @@ -182,6 +182,9 @@ public: void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } const std::vector& getPredecessors() const { return predecessors; } const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } void setUnreachable() { unreachable = true; } bool isUnreachable() const { return unreachable; } // Returns the block's merge instruction, if one exists (otherwise null). @@ -275,6 +278,7 @@ public: Module& getParent() const { return parent; } Block* getEntryBlock() const { return blocks.front(); } Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } void addLocalVariable(std::unique_ptr inst); Id getReturnType() const { return functionInstruction.getTypeId(); } void dump(std::vector& out) const @@ -326,6 +330,7 @@ public: } Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); } StorageClass getStorageClass(Id typeId) const {