mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
Remove dead shader instruction cycles with linear liveness traversal
This commit is contained in:
@@ -152,6 +152,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
friend void EliminateDeadCode(const std::vector<Block*>& blocks);
|
||||
|
||||
void AddUse(Inst* used, size_t operand);
|
||||
void RemoveUse(Inst* used, size_t operand);
|
||||
void ClearArgs();
|
||||
@@ -161,6 +163,7 @@ private:
|
||||
|
||||
ValueOpcode opcode;
|
||||
uint8_t num_args;
|
||||
bool live = false;
|
||||
mutable uint32_t evaluation_index = UINT32_MAX;
|
||||
uint64_t flags;
|
||||
Block* parent = nullptr;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/DeadCodeElimination.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
void RemoveIdentities(const BlockList& blocks) {
|
||||
@@ -18,23 +20,32 @@ void RemoveIdentities(const BlockList& blocks) {
|
||||
}
|
||||
|
||||
void EliminateDeadCode(const BlockList& blocks) {
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
for (auto block = blocks.rbegin(); block != blocks.rend(); block++) {
|
||||
auto& instructions = (*block)->Instructions();
|
||||
auto inst = instructions.end();
|
||||
while (inst != instructions.begin()) {
|
||||
--inst;
|
||||
if (inst->HasUses() || inst->MayHaveSideEffects()) {
|
||||
continue;
|
||||
}
|
||||
inst->Invalidate();
|
||||
inst = instructions.erase(inst);
|
||||
changed = true;
|
||||
std::vector<Inst*> pending;
|
||||
for (auto* block: blocks) {
|
||||
for (auto& inst: *block) {
|
||||
// Retained resource-planning instructions live outside the block list.
|
||||
inst.live = inst.MayHaveSideEffects() || std::ranges::any_of(inst.Uses(),
|
||||
[](const Use& use) { return use.user->Parent() == nullptr; });
|
||||
if (inst.live) pending.push_back(&inst);
|
||||
}
|
||||
}
|
||||
while (!pending.empty()) {
|
||||
const auto* inst = pending.back();
|
||||
pending.pop_back();
|
||||
for (size_t arg = 0; arg < inst->NumArgs(); ++arg) {
|
||||
auto* input = inst->Arg(arg).TryInstruction();
|
||||
if (input != nullptr && input->Parent() != nullptr && !input->live) {
|
||||
input->live = true;
|
||||
pending.push_back(input);
|
||||
}
|
||||
}
|
||||
} while (changed);
|
||||
}
|
||||
// Unlink every dead operand before freeing nodes in a dead Phi cycle.
|
||||
for (auto* block: blocks)
|
||||
for (auto& inst: *block)
|
||||
if (!inst.live) inst.Invalidate();
|
||||
for (auto* block: blocks)
|
||||
std::erase_if(block->Instructions(), [](const Inst& inst) { return !inst.live; });
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
Reference in New Issue
Block a user