// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "shader_recompiler/ir/attribute.h" #include "shader_recompiler/ir/value.h" namespace Shader::Optimiation::PatternMatching { // Attempt at pattern matching for Insts and Values // Needs improvement, mostly a convenience template struct MatchObject { inline bool Match(IR::Value v) { return static_cast(this)->Match(v); } }; struct MatchValue : MatchObject { MatchValue(IR::Value& return_val_) : return_val(return_val_) {} inline bool Match(IR::Value v) { return_val = v; return true; } private: IR::Value& return_val; }; struct MatchIgnore : MatchObject { MatchIgnore() {} inline bool Match(IR::Value v) { return true; } }; struct MatchImm : MatchObject { MatchImm(IR::Value& v) : return_val(v) {} inline bool Match(IR::Value v) { if (!v.IsImmediate()) { return false; } return_val = v; return true; } private: IR::Value& return_val; }; struct MatchAttribute : MatchObject { MatchAttribute(IR::Attribute attribute_) : attribute(attribute_) {} inline bool Match(IR::Value v) { return v.Type() == IR::Type::Attribute && v.Attribute() == attribute; } private: IR::Attribute attribute; }; struct MatchU32 : MatchObject { MatchU32(u32 imm_) : imm(imm_) {} inline bool Match(IR::Value v) { return v.IsImmediate() && v.Type() == IR::Type::U32 && v.U32() == imm; } private: u32 imm; }; template struct MatchInstObject : MatchObject> { static_assert(sizeof...(Args) == IR::NumArgsOf(opcode)); MatchInstObject(Args&&... args) : pattern(std::forward_as_tuple(args...)) {} inline bool Match(IR::Value v) { IR::Inst* inst = v.TryInstRecursive(); if (!inst || inst->GetOpcode() != opcode) { return false; } bool matched = true; [&](std::index_sequence) { ((matched = matched && std::get(pattern).Match(inst->Arg(Is))), ...); }(std::make_index_sequence{}); return matched; } private: using MatchArgs = std::tuple; MatchArgs pattern; }; template inline auto MakeInstPattern(Args&&... args) { return MatchInstObject(std::forward(args)...); } // Conveniences. TODO probably simpler way of doing this #define M_READCONST(...) MakeInstPattern(__VA_ARGS__) #define M_GETUSERDATA(...) MakeInstPattern(__VA_ARGS__) #define M_BITFIELDUEXTRACT(...) MakeInstPattern(__VA_ARGS__) #define M_BITFIELDSEXTRACT(...) MakeInstPattern(__VA_ARGS__) #define M_GETATTRIBUTEU32(...) MakeInstPattern(__VA_ARGS__) #define M_UMOD32(...) MakeInstPattern(__VA_ARGS__) #define M_SHIFTRIGHTLOGICAL32(...) MakeInstPattern(__VA_ARGS__) #define M_IADD32(...) MakeInstPattern(__VA_ARGS__) #define M_IMUL32(...) MakeInstPattern(__VA_ARGS__) #define M_BITWISEAND32(...) MakeInstPattern(__VA_ARGS__) #define M_GETTESSGENERICATTRIBUTE(...) \ MakeInstPattern(__VA_ARGS__) #define M_SETTCSGENERICATTRIBUTE(...) \ MakeInstPattern(__VA_ARGS__) #define M_COMPOSITECONSTRUCTU32X2(...) \ MakeInstPattern(__VA_ARGS__) #define M_COMPOSITECONSTRUCTU32X4(...) \ MakeInstPattern(__VA_ARGS__) } // namespace Shader::Optimiation::PatternMatching