/* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD */ #pragma once #include #include #include #include #include #include #include #include #include #include "frontend/ir/microinstruction.h" #include "frontend/ir/opcodes.h" #include "frontend/ir/value.h" namespace Dynarmic::Optimization::IRMatcher { struct CaptureValue { using ReturnType = std::tuple; static std::optional Match(IR::Value value) { return std::tuple(value); } }; struct CaptureInst { using ReturnType = std::tuple; static std::optional Match(IR::Value value) { if (value.IsImmediate()) return std::nullopt; return std::tuple(value.GetInstRecursive()); } }; struct CaptureUImm { using ReturnType = std::tuple; static std::optional Match(IR::Value value) { return std::tuple(value.GetImmediateAsU64()); } }; struct CaptureSImm { using ReturnType = std::tuple; static std::optional Match(IR::Value value) { return std::tuple(value.GetImmediateAsS64()); } }; template struct UImm { using ReturnType = std::tuple<>; static std::optional> Match(IR::Value value) { if (value.GetImmediateAsU64() == Value) return std::tuple(); return std::nullopt; } }; template struct SImm { using ReturnType = std::tuple<>; static std::optional> Match(IR::Value value) { if (value.GetImmediateAsS64() == Value) return std::tuple(); return std::nullopt; } }; template struct Inst { public: using ReturnType = mp::concat, typename Args::ReturnType...>; static std::optional Match(const IR::Inst& inst) { if (inst.GetOpcode() != Opcode) return std::nullopt; if (inst.HasAssociatedPseudoOperation()) return std::nullopt; return MatchArgs<0>(inst); } static std::optional Match(IR::Value value) { if (value.IsImmediate()) return std::nullopt; return Match(*value.GetInstRecursive()); } private: template static auto MatchArgs(const IR::Inst& inst) -> std::optional>, std::tuple<>>>> { if constexpr (I >= sizeof...(Args)) { return std::tuple(); } else { using Arg = mp::get>; if (const auto arg = Arg::Match(inst.GetArg(I))) { if (const auto rest = MatchArgs(inst)) { return std::tuple_cat(*arg, *rest); } } return std::nullopt; } } }; inline bool IsSameInst(std::tuple t) { return std::get<0>(t) == std::get<1>(t); } inline bool IsSameInst(std::tuple t) { return std::get<0>(t) == std::get<1>(t) && std::get<0>(t) == std::get<2>(t); } } // namespace Dynarmic::Optimization::IRMatcher