shader_ir: Implement immediate register tracking

This commit is contained in:
ReinUsesLisp 2019-03-29 18:36:07 -03:00
parent f770c17d01
commit cf4ecc1945
2 changed files with 19 additions and 1 deletions

View file

@ -7,6 +7,7 @@
#include <array> #include <array>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <optional>
#include <set> #include <set>
#include <string> #include <string>
#include <tuple> #include <tuple>
@ -773,6 +774,8 @@ private:
Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor); Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor);
std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor);
std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, s64 cursor); std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, s64 cursor);
template <typename... T> template <typename... T>

View file

@ -6,6 +6,7 @@
#include <utility> #include <utility>
#include <variant> #include <variant>
#include "common/common_types.h"
#include "video_core/shader/shader_ir.h" #include "video_core/shader/shader_ir.h"
namespace VideoCommon::Shader { namespace VideoCommon::Shader {
@ -14,7 +15,7 @@ namespace {
std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
OperationCode operation_code) { OperationCode operation_code) {
for (; cursor >= 0; --cursor) { for (; cursor >= 0; --cursor) {
const Node node = code[cursor]; const Node node = code.at(cursor);
if (const auto operation = std::get_if<OperationNode>(node)) { if (const auto operation = std::get_if<OperationNode>(node)) {
if (operation->GetCode() == operation_code) if (operation->GetCode() == operation_code)
return {node, cursor}; return {node, cursor};
@ -64,6 +65,20 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) {
return nullptr; return nullptr;
} }
std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) {
// Reduce the cursor in one to avoid infinite loops when the instruction sets the same register
// that it uses as operand
const auto [found, found_cursor] =
TrackRegister(&std::get<GprNode>(*tracked), code, cursor - 1);
if (!found) {
return {};
}
if (const auto immediate = std::get_if<ImmediateNode>(found)) {
return immediate->GetValue();
}
return {};
}
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeBlock& code, std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeBlock& code,
s64 cursor) { s64 cursor) {
for (; cursor >= 0; --cursor) { for (; cursor >= 0; --cursor) {