mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-01 23:12:35 +00:00
Num executions
This commit is contained in:
parent
418f7daa57
commit
da65ae3bcb
@ -875,6 +875,8 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/ir_emitter.cpp
|
src/shader_recompiler/ir/ir_emitter.cpp
|
||||||
src/shader_recompiler/ir/ir_emitter.h
|
src/shader_recompiler/ir/ir_emitter.h
|
||||||
src/shader_recompiler/ir/microinstruction.cpp
|
src/shader_recompiler/ir/microinstruction.cpp
|
||||||
|
src/shader_recompiler/ir/num_executions.cpp
|
||||||
|
src/shader_recompiler/ir/num_executions.cpp
|
||||||
src/shader_recompiler/ir/opcodes.cpp
|
src/shader_recompiler/ir/opcodes.cpp
|
||||||
src/shader_recompiler/ir/opcodes.h
|
src/shader_recompiler/ir/opcodes.h
|
||||||
src/shader_recompiler/ir/opcodes.inc
|
src/shader_recompiler/ir/opcodes.inc
|
||||||
|
@ -23,7 +23,7 @@ static void Invoke(ImmValueList& inst_values, const std::array<ImmValueList, siz
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <auto func>
|
template <auto func>
|
||||||
static void Invoke(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache& cache) {
|
static void Invoke(Inst* inst, ImmValueList& inst_values, Cache& cache) {
|
||||||
using Traits = Common::FuncTraits<decltype(func)>;
|
using Traits = Common::FuncTraits<decltype(func)>;
|
||||||
constexpr size_t num_args = Traits::NUM_ARGS - 1;
|
constexpr size_t num_args = Traits::NUM_ARGS - 1;
|
||||||
ASSERT(inst->NumArgs() >= num_args);
|
ASSERT(inst->NumArgs() >= num_args);
|
||||||
@ -34,8 +34,7 @@ static void Invoke(Inst* inst, ImmValueList& inst_values, ComputeImmValuesCache&
|
|||||||
Invoke<func>(inst_values, args, std::make_index_sequence<num_args>{});
|
Invoke<func>(inst_values, args, std::make_index_sequence<num_args>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DoInstructionOperation(Inst* inst, ImmValueList& inst_values,
|
static void DoInstructionOperation(Inst* inst, ImmValueList& inst_values, Cache& cache) {
|
||||||
ComputeImmValuesCache& cache) {
|
|
||||||
switch (inst->GetOpcode()) {
|
switch (inst->GetOpcode()) {
|
||||||
#define OPCODE(name, result_type, ...) \
|
#define OPCODE(name, result_type, ...) \
|
||||||
case Opcode::name: \
|
case Opcode::name: \
|
||||||
@ -64,7 +63,7 @@ static bool IsSelectInst(Inst* inst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compute(const Value& value, ImmValueList& values, ComputeImmValuesCache& cache) {
|
void Compute(const Value& value, ImmValueList& values, Cache& cache) {
|
||||||
Value resolved = value.Resolve();
|
Value resolved = value.Resolve();
|
||||||
if (ImmValue::IsSupportedValue(resolved)) {
|
if (ImmValue::IsSupportedValue(resolved)) {
|
||||||
values.insert(ImmValue(resolved));
|
values.insert(ImmValue(resolved));
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
namespace Shader::IR::ComputeValue {
|
namespace Shader::IR::ComputeValue {
|
||||||
|
|
||||||
using ImmValueList = std::unordered_set<ImmValue>;
|
using ImmValueList = std::unordered_set<ImmValue>;
|
||||||
using ComputeImmValuesCache = boost::container::flat_map<Inst*, ImmValueList>;
|
using Cache = boost::container::flat_map<Inst*, ImmValueList>;
|
||||||
|
|
||||||
void Compute(const Value& value, ImmValueList& values, ComputeImmValuesCache& cache);
|
void Compute(const Value& value, ImmValueList& values, Cache& cache);
|
||||||
|
|
||||||
} // namespace Shader::IR::ComputeValue
|
} // namespace Shader::IR::ComputeValue
|
61
src/shader_recompiler/ir/num_executions.cpp
Normal file
61
src/shader_recompiler/ir/num_executions.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/cartesian_invoke.h"
|
||||||
|
#include "shader_recompiler/ir/basic_block.h"
|
||||||
|
#include "shader_recompiler/ir/compute_value/compute.h"
|
||||||
|
#include "shader_recompiler/ir/num_executions.h"
|
||||||
|
|
||||||
|
namespace Shader::IR {
|
||||||
|
|
||||||
|
static bool Is64BitCondition(const Inst* inst) {
|
||||||
|
switch (inst->GetOpcode()) {
|
||||||
|
case Opcode::SLessThan64:
|
||||||
|
case Opcode::ULessThan64:
|
||||||
|
case Opcode::IEqual64:
|
||||||
|
case Opcode::INotEqual64:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 GetDistance32(const ComputeValue::ImmValue& a, const ComputeValue::ImmValue& b) {
|
||||||
|
return a.U32() < b.U32() ? b.U32() - a.U32() : a.U32() - b.U32();
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 GetDistance64(const ComputeValue::ImmValue& a, const ComputeValue::ImmValue& b) {
|
||||||
|
return a.U64() < b.U64() ? b.U64() - a.U64() : a.U64() - b.U64();
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetNumExecutions(const Inst* inst) {
|
||||||
|
u64 num_executions = 1;
|
||||||
|
const auto* cond_data = &inst->GetParent()->CondData();
|
||||||
|
while (cond_data->asl_node) {
|
||||||
|
if (cond_data->asl_node->type == AbstractSyntaxNode::Type::Loop) {
|
||||||
|
ComputeValue::ImmValueList cond_arg0, cond_arg1;
|
||||||
|
ComputeValue::Cache cache;
|
||||||
|
Block* cont_block = cond_data->asl_node->data.loop.continue_block;
|
||||||
|
Inst* cond_inst = cont_block->back().Arg(0).InstRecursive();
|
||||||
|
ASSERT(cond_inst);
|
||||||
|
ComputeValue::Compute(cond_inst->Arg(0), cond_arg0, cache);
|
||||||
|
ComputeValue::Compute(cond_inst->Arg(1), cond_arg1, cache);
|
||||||
|
std::unordered_set<u64> distances;
|
||||||
|
if (Is64BitCondition(cond_inst)) {
|
||||||
|
Common::CartesianInvoke(GetDistance64,
|
||||||
|
std::insert_iterator(distances, distances.end()), cond_arg0,
|
||||||
|
cond_arg1);
|
||||||
|
} else {
|
||||||
|
Common::CartesianInvoke(GetDistance32,
|
||||||
|
std::insert_iterator(distances, distances.end()), cond_arg0,
|
||||||
|
cond_arg1);
|
||||||
|
}
|
||||||
|
num_executions *=
|
||||||
|
std::max<u64>(1, *std::max_element(distances.begin(), distances.end()));
|
||||||
|
}
|
||||||
|
cond_data = cond_data->parent;
|
||||||
|
}
|
||||||
|
return num_executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::IR
|
16
src/shader_recompiler/ir/num_executions.h
Normal file
16
src/shader_recompiler/ir/num_executions.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "shader_recompiler/ir/type.h"
|
||||||
|
|
||||||
|
// Get the number of times an instruction will be executed.
|
||||||
|
// 0 if it cannot be determined statically.
|
||||||
|
|
||||||
|
namespace Shader::IR {
|
||||||
|
|
||||||
|
u64 GetNumExecutions(const Inst* inst);
|
||||||
|
|
||||||
|
} // namespace Shader::IR
|
Loading…
Reference in New Issue
Block a user