mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 16:32:39 +00:00
add use tracking for Insts
This commit is contained in:
parent
7b16085c59
commit
6036cc8f79
@ -1,6 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -116,10 +116,10 @@ void Inst::SetArg(size_t index, Value value) {
|
|||||||
}
|
}
|
||||||
const IR::Value arg{Arg(index)};
|
const IR::Value arg{Arg(index)};
|
||||||
if (!arg.IsImmediate()) {
|
if (!arg.IsImmediate()) {
|
||||||
UndoUse(arg);
|
UndoUse(arg.Inst());
|
||||||
}
|
}
|
||||||
if (!value.IsImmediate()) {
|
if (!value.IsImmediate()) {
|
||||||
Use(value);
|
Use(value.Inst(), index);
|
||||||
}
|
}
|
||||||
if (op == Opcode::Phi) {
|
if (op == Opcode::Phi) {
|
||||||
phi_args[index].second = value;
|
phi_args[index].second = value;
|
||||||
@ -140,12 +140,13 @@ Block* Inst::PhiBlock(size_t index) const {
|
|||||||
|
|
||||||
void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
|
void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
|
||||||
if (!value.IsImmediate()) {
|
if (!value.IsImmediate()) {
|
||||||
Use(value);
|
Use(value.Inst(), phi_args.size());
|
||||||
}
|
}
|
||||||
phi_args.emplace_back(predecessor, value);
|
phi_args.emplace_back(predecessor, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::Invalidate() {
|
void Inst::Invalidate() {
|
||||||
|
ASSERT(uses.empty());
|
||||||
ClearArgs();
|
ClearArgs();
|
||||||
ReplaceOpcode(Opcode::Void);
|
ReplaceOpcode(Opcode::Void);
|
||||||
}
|
}
|
||||||
@ -155,14 +156,14 @@ void Inst::ClearArgs() {
|
|||||||
for (auto& pair : phi_args) {
|
for (auto& pair : phi_args) {
|
||||||
IR::Value& value{pair.second};
|
IR::Value& value{pair.second};
|
||||||
if (!value.IsImmediate()) {
|
if (!value.IsImmediate()) {
|
||||||
UndoUse(value);
|
UndoUse(value.Inst());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
phi_args.clear();
|
phi_args.clear();
|
||||||
} else {
|
} else {
|
||||||
for (auto& value : args) {
|
for (auto& value : args) {
|
||||||
if (!value.IsImmediate()) {
|
if (!value.IsImmediate()) {
|
||||||
UndoUse(value);
|
UndoUse(value.Inst());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reset arguments to null
|
// Reset arguments to null
|
||||||
@ -172,12 +173,13 @@ void Inst::ClearArgs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Inst::ReplaceUsesWith(Value replacement) {
|
void Inst::ReplaceUsesWith(Value replacement) {
|
||||||
Invalidate();
|
|
||||||
ReplaceOpcode(Opcode::Identity);
|
|
||||||
if (!replacement.IsImmediate()) {
|
if (!replacement.IsImmediate()) {
|
||||||
Use(replacement);
|
for (auto& [user, operand] : uses) {
|
||||||
|
user->SetArg(operand, replacement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
args[0] = replacement;
|
uses.clear();
|
||||||
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::ReplaceOpcode(IR::Opcode opcode) {
|
void Inst::ReplaceOpcode(IR::Opcode opcode) {
|
||||||
@ -192,14 +194,12 @@ void Inst::ReplaceOpcode(IR::Opcode opcode) {
|
|||||||
op = opcode;
|
op = opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::Use(const Value& value) {
|
void Inst::Use(Inst* used, u32 operand) {
|
||||||
Inst* const inst{value.Inst()};
|
used->uses.emplace_front(this, operand);
|
||||||
++inst->use_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::UndoUse(const Value& value) {
|
void Inst::UndoUse(Inst* used) {
|
||||||
Inst* const inst{value.Inst()};
|
used->uses.remove_if([this](const IR::Use& use) { return use.user == this; });
|
||||||
--inst->use_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::IR
|
} // namespace Shader::IR
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <boost/container/list.hpp>
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
|
|
||||||
@ -15,6 +16,7 @@
|
|||||||
#include "shader_recompiler/exception.h"
|
#include "shader_recompiler/exception.h"
|
||||||
#include "shader_recompiler/ir/attribute.h"
|
#include "shader_recompiler/ir/attribute.h"
|
||||||
#include "shader_recompiler/ir/opcodes.h"
|
#include "shader_recompiler/ir/opcodes.h"
|
||||||
|
#include "shader_recompiler/ir/patch.h"
|
||||||
#include "shader_recompiler/ir/reg.h"
|
#include "shader_recompiler/ir/reg.h"
|
||||||
#include "shader_recompiler/ir/type.h"
|
#include "shader_recompiler/ir/type.h"
|
||||||
|
|
||||||
@ -104,6 +106,11 @@ public:
|
|||||||
explicit TypedValue(IR::Inst* inst_) : TypedValue(Value(inst_)) {}
|
explicit TypedValue(IR::Inst* inst_) : TypedValue(Value(inst_)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Use {
|
||||||
|
Inst* user;
|
||||||
|
u32 operand;
|
||||||
|
};
|
||||||
|
|
||||||
class Inst : public boost::intrusive::list_base_hook<> {
|
class Inst : public boost::intrusive::list_base_hook<> {
|
||||||
public:
|
public:
|
||||||
explicit Inst(IR::Opcode op_, u32 flags_) noexcept;
|
explicit Inst(IR::Opcode op_, u32 flags_) noexcept;
|
||||||
@ -117,12 +124,12 @@ public:
|
|||||||
|
|
||||||
/// Get the number of uses this instruction has.
|
/// Get the number of uses this instruction has.
|
||||||
[[nodiscard]] int UseCount() const noexcept {
|
[[nodiscard]] int UseCount() const noexcept {
|
||||||
return use_count;
|
return uses.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines whether this instruction has uses or not.
|
/// Determines whether this instruction has uses or not.
|
||||||
[[nodiscard]] bool HasUses() const noexcept {
|
[[nodiscard]] bool HasUses() const noexcept {
|
||||||
return use_count > 0;
|
return uses.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the opcode this microinstruction represents.
|
/// Get the opcode this microinstruction represents.
|
||||||
@ -199,11 +206,10 @@ private:
|
|||||||
NonTriviallyDummy() noexcept {}
|
NonTriviallyDummy() noexcept {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Use(const Value& value);
|
void Use(Inst* used, u32 operand);
|
||||||
void UndoUse(const Value& value);
|
void UndoUse(Inst* used);
|
||||||
|
|
||||||
IR::Opcode op{};
|
IR::Opcode op{};
|
||||||
int use_count{};
|
|
||||||
u32 flags{};
|
u32 flags{};
|
||||||
u32 definition{};
|
u32 definition{};
|
||||||
union {
|
union {
|
||||||
@ -211,8 +217,10 @@ private:
|
|||||||
boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args;
|
boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args;
|
||||||
std::array<Value, 6> args;
|
std::array<Value, 6> args;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::container::list<IR::Use> uses;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased");
|
static_assert(sizeof(Inst) <= 152, "Inst size unintentionally increased");
|
||||||
|
|
||||||
using U1 = TypedValue<Type::U1>;
|
using U1 = TypedValue<Type::U1>;
|
||||||
using U8 = TypedValue<Type::U8>;
|
using U8 = TypedValue<Type::U8>;
|
||||||
|
Loading…
Reference in New Issue
Block a user