mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
Inline common IR operands and share storage with Phi pairs
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
@@ -135,10 +135,16 @@ bool Value::operator==(const Value& other) const {
|
||||
}
|
||||
|
||||
Inst::Inst(ValueOpcode value_opcode, uint64_t value_flags)
|
||||
: opcode(value_opcode), flags(value_flags) {
|
||||
const auto count = NumArgsOf(opcode);
|
||||
if (count != std::numeric_limits<size_t>::max()) {
|
||||
args.resize(count);
|
||||
: opcode(value_opcode),
|
||||
num_args(value_opcode == ValueOpcode::Phi ? PhiArity
|
||||
: static_cast<uint8_t>(NumArgsOf(value_opcode))),
|
||||
flags(value_flags) {
|
||||
if (num_args == PhiArity) {
|
||||
std::destroy_at(&fixed_args);
|
||||
std::construct_at(&phi_args);
|
||||
} else if (num_args > InlineArity) {
|
||||
std::destroy_at(&fixed_args);
|
||||
std::construct_at(&large_args, num_args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,8 +160,8 @@ Type Inst::GetType() const {
|
||||
if (opcode == ValueOpcode::Phi) {
|
||||
return static_cast<Type>(flags);
|
||||
}
|
||||
if (opcode == ValueOpcode::Identity && !args.empty()) {
|
||||
return args.front().GetType();
|
||||
if (opcode == ValueOpcode::Identity && num_args != 0) {
|
||||
return Arg(0).GetType();
|
||||
}
|
||||
return TypeOf(opcode);
|
||||
}
|
||||
@@ -173,21 +179,25 @@ size_t Inst::UseCount() const {
|
||||
}
|
||||
|
||||
size_t Inst::NumArgs() const {
|
||||
return args.size();
|
||||
return num_args == PhiArity ? phi_args.size() : num_args;
|
||||
}
|
||||
|
||||
size_t Inst::NumPhiBlocks() const {
|
||||
return phi_blocks.size();
|
||||
return num_args == PhiArity ? phi_args.size() : 0;
|
||||
}
|
||||
|
||||
Value Inst::Arg(size_t index) const {
|
||||
EXIT_IF(index >= args.size());
|
||||
return args[index];
|
||||
if (num_args <= InlineArity) {
|
||||
EXIT_IF(index >= num_args);
|
||||
return fixed_args[index];
|
||||
}
|
||||
EXIT_IF(index >= NumArgs());
|
||||
return num_args == PhiArity ? phi_args[index].second : large_args[index];
|
||||
}
|
||||
|
||||
Block* Inst::PhiBlock(size_t index) const {
|
||||
EXIT_IF(opcode != ValueOpcode::Phi || index >= phi_blocks.size());
|
||||
return phi_blocks[index];
|
||||
EXIT_IF(opcode != ValueOpcode::Phi || index >= phi_args.size());
|
||||
return phi_args[index].first;
|
||||
}
|
||||
|
||||
Block* Inst::Parent() const {
|
||||
@@ -203,15 +213,17 @@ void Inst::SetParent(Block* block) {
|
||||
}
|
||||
|
||||
void Inst::SetArg(size_t index, Value value) {
|
||||
if (index >= args.size()) {
|
||||
EXIT_IF(NumArgsOf(opcode) != std::numeric_limits<size_t>::max());
|
||||
args.resize(index + 1);
|
||||
}
|
||||
const auto old = args[index];
|
||||
const auto old = Arg(index);
|
||||
if (auto* old_inst = old.TryInstruction(); old_inst != nullptr) {
|
||||
RemoveUse(old_inst, index);
|
||||
}
|
||||
args[index] = value;
|
||||
if (num_args <= InlineArity) {
|
||||
fixed_args[index] = value;
|
||||
} else if (num_args == PhiArity) {
|
||||
phi_args[index].second = value;
|
||||
} else {
|
||||
large_args[index] = value;
|
||||
}
|
||||
if (auto* new_inst = value.TryInstruction(); new_inst != nullptr) {
|
||||
AddUse(new_inst, index);
|
||||
}
|
||||
@@ -219,9 +231,8 @@ void Inst::SetArg(size_t index, Value value) {
|
||||
|
||||
void Inst::AddPhiOperand(Block* predecessor, Value value) {
|
||||
EXIT_IF(opcode != ValueOpcode::Phi);
|
||||
const auto index = args.size();
|
||||
args.push_back(value);
|
||||
phi_blocks.push_back(predecessor);
|
||||
const auto index = phi_args.size();
|
||||
phi_args.emplace_back(predecessor, value);
|
||||
if (auto* value_inst = value.TryInstruction(); value_inst != nullptr) {
|
||||
AddUse(value_inst, index);
|
||||
}
|
||||
@@ -234,21 +245,12 @@ void Inst::ReplaceUsesWith(Value replacement, bool preserve) {
|
||||
}
|
||||
Invalidate();
|
||||
if (preserve) {
|
||||
ReplaceOpcode(ValueOpcode::Identity);
|
||||
args.resize(1);
|
||||
opcode = ValueOpcode::Identity;
|
||||
num_args = 1;
|
||||
SetArg(0, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
void Inst::ReplaceOpcode(ValueOpcode value_opcode) {
|
||||
opcode = value_opcode;
|
||||
const auto count = NumArgsOf(opcode);
|
||||
if (count != std::numeric_limits<size_t>::max()) {
|
||||
EXIT_IF(!args.empty() && args.size() != count);
|
||||
args.resize(count);
|
||||
}
|
||||
}
|
||||
|
||||
void Inst::Invalidate() {
|
||||
ClearArgs();
|
||||
opcode = ValueOpcode::Void;
|
||||
@@ -269,13 +271,21 @@ void Inst::RemoveUse(Inst* used, size_t operand) {
|
||||
}
|
||||
|
||||
void Inst::ClearArgs() {
|
||||
for (size_t index = 0; index < args.size(); index++) {
|
||||
if (auto* value_inst = args[index].TryInstruction(); value_inst != nullptr) {
|
||||
for (size_t index = 0; index < NumArgs(); index++) {
|
||||
if (auto* value_inst = Arg(index).TryInstruction(); value_inst != nullptr) {
|
||||
RemoveUse(value_inst, index);
|
||||
}
|
||||
}
|
||||
args.clear();
|
||||
phi_blocks.clear();
|
||||
if (num_args == PhiArity) {
|
||||
std::destroy_at(&phi_args);
|
||||
std::construct_at(&fixed_args);
|
||||
} else if (num_args > InlineArity) {
|
||||
std::destroy_at(&large_args);
|
||||
std::construct_at(&fixed_args);
|
||||
} else {
|
||||
fixed_args.fill(Value {});
|
||||
}
|
||||
num_args = 0;
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
Reference in New Issue
Block a user