summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/frontend/ir/microinstruction.h
blob: 7f1ed6710c84d9a254c6918488b38acec6cdb0f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <array>
#include <span>
#include <vector>

#include <boost/intrusive/list.hpp>

#include "common/common_types.h"
#include "shader_recompiler/frontend/ir/opcode.h"
#include "shader_recompiler/frontend/ir/type.h"
#include "shader_recompiler/frontend/ir/value.h"

namespace Shader::IR {

class Block;

constexpr size_t MAX_ARG_COUNT = 4;

class Inst : public boost::intrusive::list_base_hook<> {
public:
    explicit Inst(Opcode op_) noexcept : op(op_) {}

    /// Get the number of uses this instruction has.
    [[nodiscard]] int UseCount() const noexcept {
        return use_count;
    }

    /// Determines whether this instruction has uses or not.
    [[nodiscard]] bool HasUses() const noexcept {
        return use_count > 0;
    }

    /// Get the opcode this microinstruction represents.
    [[nodiscard]] IR::Opcode Opcode() const noexcept {
        return op;
    }

    /// Determines whether or not this instruction may have side effects.
    [[nodiscard]] bool MayHaveSideEffects() const noexcept;

    /// Determines whether or not this instruction is a pseudo-instruction.
    /// Pseudo-instructions depend on their parent instructions for their semantics.
    [[nodiscard]] bool IsPseudoInstruction() const noexcept;

    /// Determines if there is a pseudo-operation associated with this instruction.
    [[nodiscard]] bool HasAssociatedPseudoOperation() const noexcept;
    /// Gets a pseudo-operation associated with this instruction
    [[nodiscard]] Inst* GetAssociatedPseudoOperation(IR::Opcode opcode);

    /// Get the number of arguments this instruction has.
    [[nodiscard]] size_t NumArgs() const;

    /// Get the type this instruction returns.
    [[nodiscard]] IR::Type Type() const;

    /// Get the value of a given argument index.
    [[nodiscard]] Value Arg(size_t index) const;
    /// Set the value of a given argument index.
    void SetArg(size_t index, Value value);

    /// Get an immutable span to the phi operands.
    [[nodiscard]] std::span<const std::pair<Block*, Value>> PhiOperands() const noexcept;
    /// Add phi operand to a phi instruction.
    void AddPhiOperand(Block* predecessor, const Value& value);

    void Invalidate();
    void ClearArgs();

    void ReplaceUsesWith(Value replacement);

private:
    void Use(const Value& value);
    void UndoUse(const Value& value);

    IR::Opcode op{};
    int use_count{};
    std::array<Value, MAX_ARG_COUNT> args{};
    Inst* zero_inst{};
    Inst* sign_inst{};
    Inst* carry_inst{};
    Inst* overflow_inst{};
    Inst* zsco_inst{};
    std::vector<std::pair<Block*, Value>> phi_operands;
    u64 flags{};
};

} // namespace Shader::IR