summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/frontend/ir/breadth_first_search.h57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/ir/breadth_first_search.h b/src/shader_recompiler/frontend/ir/breadth_first_search.h
new file mode 100644
index 000000000..b35f062d4
--- /dev/null
+++ b/src/shader_recompiler/frontend/ir/breadth_first_search.h
@@ -0,0 +1,57 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <optional>
8#include <type_traits>
9#include <queue>
10
11#include <boost/container/small_vector.hpp>
12
13#include "shader_recompiler/frontend/ir/microinstruction.h"
14#include "shader_recompiler/frontend/ir/value.h"
15
16namespace Shader::IR {
17
18template <typename Pred>
19auto BreadthFirstSearch(const Value& value, Pred&& pred)
20 -> std::invoke_result_t<Pred, const Inst*> {
21 if (value.IsImmediate()) {
22 // Nothing to do with immediates
23 return std::nullopt;
24 }
25 // Breadth-first search visiting the right most arguments first
26 // Small vector has been determined from shaders in Super Smash Bros. Ultimate
27 boost::container::small_vector<const Inst*, 2> visited;
28 std::queue<const Inst*> queue;
29 queue.push(value.InstRecursive());
30
31 while (!queue.empty()) {
32 // Pop one instruction from the queue
33 const Inst* const inst{queue.front()};
34 queue.pop();
35 if (const std::optional result = pred(inst)) {
36 // This is the instruction we were looking for
37 return result;
38 }
39 // Visit the right most arguments first
40 for (size_t arg = inst->NumArgs(); arg--;) {
41 const Value arg_value{inst->Arg(arg)};
42 if (arg_value.IsImmediate()) {
43 continue;
44 }
45 // Queue instruction if it hasn't been visited
46 const Inst* const arg_inst{arg_value.InstRecursive()};
47 if (std::ranges::find(visited, arg_inst) == visited.end()) {
48 visited.push_back(arg_inst);
49 queue.push(arg_inst);
50 }
51 }
52 }
53 // SSA tree has been traversed and the result hasn't been found
54 return std::nullopt;
55}
56
57} // namespace Shader::IR