shader: Constant propagation and global memory to storage buffer

This commit is contained in:
ReinUsesLisp 2021-02-05 05:58:02 -03:00 committed by ameerj
parent d24a16045f
commit e81739493a
17 changed files with 652 additions and 63 deletions

View file

@ -14,8 +14,6 @@
// https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6
//
#include <map>
#include <boost/container/flat_map.hpp>
#include "shader_recompiler/frontend/ir/basic_block.h"
@ -30,6 +28,12 @@ namespace Shader::Optimization {
namespace {
using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>;
struct FlagTag {};
struct ZeroFlagTag : FlagTag {};
struct SignFlagTag : FlagTag {};
struct CarryFlagTag : FlagTag {};
struct OverflowFlagTag : FlagTag {};
struct DefTable {
[[nodiscard]] ValueMap& operator[](IR::Reg variable) noexcept {
return regs[IR::RegIndex(variable)];
@ -39,8 +43,28 @@ struct DefTable {
return preds[IR::PredIndex(variable)];
}
[[nodiscard]] ValueMap& operator[](ZeroFlagTag) noexcept {
return zero_flag;
}
[[nodiscard]] ValueMap& operator[](SignFlagTag) noexcept {
return sign_flag;
}
[[nodiscard]] ValueMap& operator[](CarryFlagTag) noexcept {
return carry_flag;
}
[[nodiscard]] ValueMap& operator[](OverflowFlagTag) noexcept {
return overflow_flag;
}
std::array<ValueMap, IR::NUM_USER_REGS> regs;
std::array<ValueMap, IR::NUM_USER_PREDS> preds;
ValueMap zero_flag;
ValueMap sign_flag;
ValueMap carry_flag;
ValueMap overflow_flag;
};
IR::Opcode UndefOpcode(IR::Reg) noexcept {
@ -51,6 +75,10 @@ IR::Opcode UndefOpcode(IR::Pred) noexcept {
return IR::Opcode::Undef1;
}
IR::Opcode UndefOpcode(const FlagTag&) noexcept {
return IR::Opcode::Undef1;
}
[[nodiscard]] bool IsPhi(const IR::Inst& inst) noexcept {
return inst.Opcode() == IR::Opcode::Phi;
}
@ -135,6 +163,18 @@ void SsaRewritePass(IR::Function& function) {
pass.WriteVariable(pred, block.get(), inst.Arg(1));
}
break;
case IR::Opcode::SetZFlag:
pass.WriteVariable(ZeroFlagTag{}, block.get(), inst.Arg(0));
break;
case IR::Opcode::SetSFlag:
pass.WriteVariable(SignFlagTag{}, block.get(), inst.Arg(0));
break;
case IR::Opcode::SetCFlag:
pass.WriteVariable(CarryFlagTag{}, block.get(), inst.Arg(0));
break;
case IR::Opcode::SetOFlag:
pass.WriteVariable(OverflowFlagTag{}, block.get(), inst.Arg(0));
break;
case IR::Opcode::GetRegister:
if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) {
inst.ReplaceUsesWith(pass.ReadVariable(reg, block.get()));
@ -145,6 +185,18 @@ void SsaRewritePass(IR::Function& function) {
inst.ReplaceUsesWith(pass.ReadVariable(pred, block.get()));
}
break;
case IR::Opcode::GetZFlag:
inst.ReplaceUsesWith(pass.ReadVariable(ZeroFlagTag{}, block.get()));
break;
case IR::Opcode::GetSFlag:
inst.ReplaceUsesWith(pass.ReadVariable(SignFlagTag{}, block.get()));
break;
case IR::Opcode::GetCFlag:
inst.ReplaceUsesWith(pass.ReadVariable(CarryFlagTag{}, block.get()));
break;
case IR::Opcode::GetOFlag:
inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block.get()));
break;
default:
break;
}