Num executions

This commit is contained in:
Lander Gallastegi 2025-03-20 12:48:36 +01:00 committed by Lander Gallastegi
parent 418f7daa57
commit da65ae3bcb
5 changed files with 84 additions and 6 deletions

View File

@ -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.h
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.h
src/shader_recompiler/ir/opcodes.inc

View File

@ -23,7 +23,7 @@ static void Invoke(ImmValueList& inst_values, const std::array<ImmValueList, siz
}
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)>;
constexpr size_t num_args = Traits::NUM_ARGS - 1;
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>{});
}
static void DoInstructionOperation(Inst* inst, ImmValueList& inst_values,
ComputeImmValuesCache& cache) {
static void DoInstructionOperation(Inst* inst, ImmValueList& inst_values, Cache& cache) {
switch (inst->GetOpcode()) {
#define OPCODE(name, result_type, ...) \
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();
if (ImmValue::IsSupportedValue(resolved)) {
values.insert(ImmValue(resolved));

View File

@ -15,8 +15,8 @@
namespace Shader::IR::ComputeValue {
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

View 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

View 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