diff options
| author | 2021-02-11 16:39:06 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:22 -0400 | |
| commit | 9170200a11715d131645d1ffb92e86e6ef0d7e88 (patch) | |
| tree | 6c6f84c38a9b59d023ecb09c0737ea56da166b64 /src/shader_recompiler/frontend/maxwell/control_flow.h | |
| parent | spirv: Initial SPIR-V support (diff) | |
| download | yuzu-9170200a11715d131645d1ffb92e86e6ef0d7e88.tar.gz yuzu-9170200a11715d131645d1ffb92e86e6ef0d7e88.tar.xz yuzu-9170200a11715d131645d1ffb92e86e6ef0d7e88.zip | |
shader: Initial implementation of an AST
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/control_flow.h')
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/control_flow.h | 77 |
1 files changed, 30 insertions, 47 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.h b/src/shader_recompiler/frontend/maxwell/control_flow.h index 49b369282..8179787b8 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.h +++ b/src/shader_recompiler/frontend/maxwell/control_flow.h | |||
| @@ -11,25 +11,27 @@ | |||
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | 12 | ||
| 13 | #include <boost/container/small_vector.hpp> | 13 | #include <boost/container/small_vector.hpp> |
| 14 | #include <boost/intrusive/set.hpp> | ||
| 14 | 15 | ||
| 15 | #include "shader_recompiler/environment.h" | 16 | #include "shader_recompiler/environment.h" |
| 16 | #include "shader_recompiler/frontend/ir/condition.h" | 17 | #include "shader_recompiler/frontend/ir/condition.h" |
| 17 | #include "shader_recompiler/frontend/maxwell/instruction.h" | 18 | #include "shader_recompiler/frontend/maxwell/instruction.h" |
| 18 | #include "shader_recompiler/frontend/maxwell/location.h" | 19 | #include "shader_recompiler/frontend/maxwell/location.h" |
| 19 | #include "shader_recompiler/frontend/maxwell/opcodes.h" | 20 | #include "shader_recompiler/frontend/maxwell/opcodes.h" |
| 21 | #include "shader_recompiler/object_pool.h" | ||
| 22 | |||
| 23 | namespace Shader::IR { | ||
| 24 | class Block; | ||
| 25 | } | ||
| 20 | 26 | ||
| 21 | namespace Shader::Maxwell::Flow { | 27 | namespace Shader::Maxwell::Flow { |
| 22 | 28 | ||
| 23 | using BlockId = u32; | ||
| 24 | using FunctionId = size_t; | 29 | using FunctionId = size_t; |
| 25 | 30 | ||
| 26 | constexpr BlockId UNREACHABLE_BLOCK_ID{static_cast<u32>(-1)}; | ||
| 27 | |||
| 28 | enum class EndClass { | 31 | enum class EndClass { |
| 29 | Branch, | 32 | Branch, |
| 30 | Exit, | 33 | Exit, |
| 31 | Return, | 34 | Return, |
| 32 | Unreachable, | ||
| 33 | }; | 35 | }; |
| 34 | 36 | ||
| 35 | enum class Token { | 37 | enum class Token { |
| @@ -59,58 +61,37 @@ private: | |||
| 59 | boost::container::small_vector<StackEntry, 3> entries; | 61 | boost::container::small_vector<StackEntry, 3> entries; |
| 60 | }; | 62 | }; |
| 61 | 63 | ||
| 62 | struct Block { | 64 | struct Block : boost::intrusive::set_base_hook< |
| 65 | // Normal link is ~2.5% faster compared to safe link | ||
| 66 | boost::intrusive::link_mode<boost::intrusive::normal_link>> { | ||
| 63 | [[nodiscard]] bool Contains(Location pc) const noexcept; | 67 | [[nodiscard]] bool Contains(Location pc) const noexcept; |
| 64 | 68 | ||
| 69 | bool operator<(const Block& rhs) const noexcept { | ||
| 70 | return begin < rhs.begin; | ||
| 71 | } | ||
| 72 | |||
| 65 | Location begin; | 73 | Location begin; |
| 66 | Location end; | 74 | Location end; |
| 67 | EndClass end_class; | 75 | EndClass end_class; |
| 68 | BlockId id; | ||
| 69 | Stack stack; | 76 | Stack stack; |
| 70 | IR::Condition cond; | 77 | IR::Condition cond; |
| 71 | BlockId branch_true; | 78 | Block* branch_true; |
| 72 | BlockId branch_false; | 79 | Block* branch_false; |
| 73 | boost::container::small_vector<BlockId, 4> imm_predecessors; | 80 | IR::Block* ir; |
| 74 | boost::container::small_vector<BlockId, 8> dominance_frontiers; | ||
| 75 | union { | ||
| 76 | bool post_order_visited{false}; | ||
| 77 | Block* imm_dominator; | ||
| 78 | }; | ||
| 79 | }; | 81 | }; |
| 80 | 82 | ||
| 81 | struct Label { | 83 | struct Label { |
| 82 | Location address; | 84 | Location address; |
| 83 | BlockId block_id; | 85 | Block* block; |
| 84 | Stack stack; | 86 | Stack stack; |
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 87 | struct Function { | 89 | struct Function { |
| 88 | Function(Location start_address); | 90 | Function(Location start_address); |
| 89 | 91 | ||
| 90 | void BuildBlocksMap(); | ||
| 91 | |||
| 92 | void BuildImmediatePredecessors(); | ||
| 93 | |||
| 94 | void BuildPostOrder(); | ||
| 95 | |||
| 96 | void BuildImmediateDominators(); | ||
| 97 | |||
| 98 | void BuildDominanceFrontier(); | ||
| 99 | |||
| 100 | [[nodiscard]] size_t NumBlocks() const noexcept { | ||
| 101 | return static_cast<size_t>(current_block_id) + 1; | ||
| 102 | } | ||
| 103 | |||
| 104 | Location entrypoint; | 92 | Location entrypoint; |
| 105 | BlockId current_block_id{0}; | ||
| 106 | boost::container::small_vector<Label, 16> labels; | 93 | boost::container::small_vector<Label, 16> labels; |
| 107 | boost::container::small_vector<u32, 0x130> blocks; | 94 | boost::intrusive::set<Block> blocks; |
| 108 | boost::container::small_vector<Block, 0x130> blocks_data; | ||
| 109 | // Translates from BlockId to block index | ||
| 110 | boost::container::small_vector<Block*, 0x130> blocks_map; | ||
| 111 | |||
| 112 | boost::container::small_vector<u32, 0x130> post_order_blocks; | ||
| 113 | boost::container::small_vector<BlockId, 0x130> post_order_map; | ||
| 114 | }; | 95 | }; |
| 115 | 96 | ||
| 116 | class CFG { | 97 | class CFG { |
| @@ -120,7 +101,7 @@ class CFG { | |||
| 120 | }; | 101 | }; |
| 121 | 102 | ||
| 122 | public: | 103 | public: |
| 123 | explicit CFG(Environment& env, Location start_address); | 104 | explicit CFG(Environment& env, ObjectPool<Block>& block_pool, Location start_address); |
| 124 | 105 | ||
| 125 | CFG& operator=(const CFG&) = delete; | 106 | CFG& operator=(const CFG&) = delete; |
| 126 | CFG(const CFG&) = delete; | 107 | CFG(const CFG&) = delete; |
| @@ -133,35 +114,37 @@ public: | |||
| 133 | [[nodiscard]] std::span<const Function> Functions() const noexcept { | 114 | [[nodiscard]] std::span<const Function> Functions() const noexcept { |
| 134 | return std::span(functions.data(), functions.size()); | 115 | return std::span(functions.data(), functions.size()); |
| 135 | } | 116 | } |
| 117 | [[nodiscard]] std::span<Function> Functions() noexcept { | ||
| 118 | return std::span(functions.data(), functions.size()); | ||
| 119 | } | ||
| 136 | 120 | ||
| 137 | private: | 121 | private: |
| 138 | void VisitFunctions(Location start_address); | ||
| 139 | |||
| 140 | void AnalyzeLabel(FunctionId function_id, Label& label); | 122 | void AnalyzeLabel(FunctionId function_id, Label& label); |
| 141 | 123 | ||
| 142 | /// Inspect already visited blocks. | 124 | /// Inspect already visited blocks. |
| 143 | /// Return true when the block has already been visited | 125 | /// Return true when the block has already been visited |
| 144 | bool InspectVisitedBlocks(FunctionId function_id, const Label& label); | 126 | bool InspectVisitedBlocks(FunctionId function_id, const Label& label); |
| 145 | 127 | ||
| 146 | AnalysisState AnalyzeInst(Block& block, FunctionId function_id, Location pc); | 128 | AnalysisState AnalyzeInst(Block* block, FunctionId function_id, Location pc); |
| 147 | 129 | ||
| 148 | void AnalyzeCondInst(Block& block, FunctionId function_id, Location pc, EndClass insn_end_class, | 130 | void AnalyzeCondInst(Block* block, FunctionId function_id, Location pc, EndClass insn_end_class, |
| 149 | IR::Condition cond); | 131 | IR::Condition cond); |
| 150 | 132 | ||
| 151 | /// Return true when the branch instruction is confirmed to be a branch | 133 | /// Return true when the branch instruction is confirmed to be a branch |
| 152 | bool AnalyzeBranch(Block& block, FunctionId function_id, Location pc, Instruction inst, | 134 | bool AnalyzeBranch(Block* block, FunctionId function_id, Location pc, Instruction inst, |
| 153 | Opcode opcode); | 135 | Opcode opcode); |
| 154 | 136 | ||
| 155 | void AnalyzeBRA(Block& block, FunctionId function_id, Location pc, Instruction inst, | 137 | void AnalyzeBRA(Block* block, FunctionId function_id, Location pc, Instruction inst, |
| 156 | bool is_absolute); | 138 | bool is_absolute); |
| 157 | void AnalyzeBRX(Block& block, Location pc, Instruction inst, bool is_absolute); | 139 | void AnalyzeBRX(Block* block, Location pc, Instruction inst, bool is_absolute); |
| 158 | void AnalyzeCAL(Location pc, Instruction inst, bool is_absolute); | 140 | void AnalyzeCAL(Location pc, Instruction inst, bool is_absolute); |
| 159 | AnalysisState AnalyzeEXIT(Block& block, FunctionId function_id, Location pc, Instruction inst); | 141 | AnalysisState AnalyzeEXIT(Block* block, FunctionId function_id, Location pc, Instruction inst); |
| 160 | 142 | ||
| 161 | /// Return the branch target block id | 143 | /// Return the branch target block id |
| 162 | BlockId AddLabel(const Block& block, Stack stack, Location pc, FunctionId function_id); | 144 | Block* AddLabel(Block* block, Stack stack, Location pc, FunctionId function_id); |
| 163 | 145 | ||
| 164 | Environment& env; | 146 | Environment& env; |
| 147 | ObjectPool<Block>& block_pool; | ||
| 165 | boost::container::small_vector<Function, 1> functions; | 148 | boost::container::small_vector<Function, 1> functions; |
| 166 | FunctionId current_function_id{0}; | 149 | FunctionId current_function_id{0}; |
| 167 | }; | 150 | }; |