shader: Implement CAL inlining function calls

This commit is contained in:
ReinUsesLisp
2021-03-14 03:41:05 -03:00
committed by ameerj
parent b9f7bf4472
commit 71f96fa636
24 changed files with 286 additions and 330 deletions

View File

@ -296,11 +296,9 @@ void Visit(Info& info, IR::Inst& inst) {
void CollectShaderInfoPass(IR::Program& program) {
Info& info{program.info};
for (IR::Function& function : program.functions) {
for (IR::Block* const block : function.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
Visit(info, inst);
}
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
Visit(info, inst);
}
}
}

View File

@ -371,9 +371,11 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
}
} // Anonymous namespace
void ConstantPropagationPass(IR::Block& block) {
for (IR::Inst& inst : block) {
ConstantPropagation(block, inst);
void ConstantPropagationPass(IR::Program& program) {
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
ConstantPropagation(*block, inst);
}
}
}

View File

@ -10,12 +10,14 @@
namespace Shader::Optimization {
void DeadCodeEliminationPass(IR::Block& block) {
void DeadCodeEliminationPass(IR::Program& program) {
// We iterate over the instructions in reverse order.
// This is because removing an instruction reduces the number of uses for earlier instructions.
for (IR::Inst& inst : block | std::views::reverse) {
if (!inst.HasUses() && !inst.MayHaveSideEffects()) {
inst.Invalidate();
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions() | std::views::reverse) {
if (!inst.HasUses() && !inst.MayHaveSideEffects()) {
inst.Invalidate();
}
}
}
}

View File

@ -351,14 +351,12 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) {
StorageBufferSet storage_buffers;
StorageInstVector to_replace;
for (IR::Function& function : program.functions) {
for (IR::Block* const block : function.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (!IsGlobalMemory(inst)) {
continue;
}
CollectStorageBuffers(*block, inst, storage_buffers, to_replace);
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (!IsGlobalMemory(inst)) {
continue;
}
CollectStorageBuffers(*block, inst, storage_buffers, to_replace);
}
}
Info& info{program.info};

View File

@ -10,10 +10,10 @@
namespace Shader::Optimization {
void IdentityRemovalPass(IR::Function& function) {
void IdentityRemovalPass(IR::Program& program) {
std::vector<IR::Inst*> to_invalidate;
for (IR::Block* const block : function.blocks) {
for (IR::Block* const block : program.blocks) {
for (auto inst = block->begin(); inst != block->end();) {
const size_t num_args{inst->NumArgs()};
for (size_t i = 0; i < num_args; ++i) {

View File

@ -77,11 +77,9 @@ IR::Opcode Replace(IR::Opcode op) {
} // Anonymous namespace
void LowerFp16ToFp32(IR::Program& program) {
for (IR::Function& function : program.functions) {
for (IR::Block* const block : function.blocks) {
for (IR::Inst& inst : block->Instructions()) {
inst.ReplaceOpcode(Replace(inst.Opcode()));
}
for (IR::Block* const block : program.blocks) {
for (IR::Inst& inst : block->Instructions()) {
inst.ReplaceOpcode(Replace(inst.Opcode()));
}
}
}

View File

@ -8,26 +8,18 @@
#include "shader_recompiler/environment.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/function.h"
#include "shader_recompiler/frontend/ir/program.h"
namespace Shader::Optimization {
template <typename Func>
void PostOrderInvoke(Func&& func, IR::Function& function) {
for (const auto& block : function.post_order_blocks) {
func(*block);
}
}
void CollectShaderInfoPass(IR::Program& program);
void ConstantPropagationPass(IR::Block& block);
void DeadCodeEliminationPass(IR::Block& block);
void ConstantPropagationPass(IR::Program& program);
void DeadCodeEliminationPass(IR::Program& program);
void GlobalMemoryToStorageBufferPass(IR::Program& program);
void IdentityRemovalPass(IR::Function& function);
void IdentityRemovalPass(IR::Program& program);
void LowerFp16ToFp32(IR::Program& program);
void SsaRewritePass(std::span<IR::Block* const> post_order_blocks);
void SsaRewritePass(IR::Program& program);
void TexturePass(Environment& env, IR::Program& program);
void VerificationPass(const IR::Function& function);
void VerificationPass(const IR::Program& program);
} // namespace Shader::Optimization

View File

@ -23,7 +23,6 @@
#include <boost/container/flat_set.hpp>
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/function.h"
#include "shader_recompiler/frontend/ir/microinstruction.h"
#include "shader_recompiler/frontend/ir/opcodes.h"
#include "shader_recompiler/frontend/ir/pred.h"
@ -262,9 +261,9 @@ void VisitBlock(Pass& pass, IR::Block* block) {
}
} // Anonymous namespace
void SsaRewritePass(std::span<IR::Block* const> post_order_blocks) {
void SsaRewritePass(IR::Program& program) {
Pass pass;
for (IR::Block* const block : post_order_blocks | std::views::reverse) {
for (IR::Block* const block : program.post_order_blocks | std::views::reverse) {
VisitBlock(pass, block);
}
}

View File

@ -164,14 +164,12 @@ private:
void TexturePass(Environment& env, IR::Program& program) {
TextureInstVector to_replace;
for (IR::Function& function : program.functions) {
for (IR::Block* const block : function.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (!IsTextureInstruction(inst)) {
continue;
}
to_replace.push_back(MakeInst(env, block, inst));
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (!IsTextureInstruction(inst)) {
continue;
}
to_replace.push_back(MakeInst(env, block, inst));
}
}
// Sort instructions to visit textures by constant buffer index, then by offset

View File

@ -11,8 +11,8 @@
namespace Shader::Optimization {
static void ValidateTypes(const IR::Function& function) {
for (const auto& block : function.blocks) {
static void ValidateTypes(const IR::Program& program) {
for (const auto& block : program.blocks) {
for (const IR::Inst& inst : *block) {
if (inst.Opcode() == IR::Opcode::Phi) {
// Skip validation on phi nodes
@ -30,9 +30,9 @@ static void ValidateTypes(const IR::Function& function) {
}
}
static void ValidateUses(const IR::Function& function) {
static void ValidateUses(const IR::Program& program) {
std::map<IR::Inst*, int> actual_uses;
for (const auto& block : function.blocks) {
for (const auto& block : program.blocks) {
for (const IR::Inst& inst : *block) {
const size_t num_args{inst.NumArgs()};
for (size_t i = 0; i < num_args; ++i) {
@ -45,14 +45,14 @@ static void ValidateUses(const IR::Function& function) {
}
for (const auto [inst, uses] : actual_uses) {
if (inst->UseCount() != uses) {
throw LogicError("Invalid uses in block:" /*, IR::DumpFunction(function)*/);
throw LogicError("Invalid uses in block: {}", IR::DumpProgram(program));
}
}
}
void VerificationPass(const IR::Function& function) {
ValidateTypes(function);
ValidateUses(function);
void VerificationPass(const IR::Program& program) {
ValidateTypes(program);
ValidateUses(program);
}
} // namespace Shader::Optimization