diff options
| author | 2021-02-02 21:07:00 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:21 -0400 | |
| commit | 6c4cc0cd062fbbba5349da1108d3c23cb330ca8a (patch) | |
| tree | 544291931da8a85fafcea71964c77d9278ec7f29 /src/shader_recompiler/frontend/ir/basic_block.cpp | |
| parent | shader: Initial recompiler work (diff) | |
| download | yuzu-6c4cc0cd062fbbba5349da1108d3c23cb330ca8a.tar.gz yuzu-6c4cc0cd062fbbba5349da1108d3c23cb330ca8a.tar.xz yuzu-6c4cc0cd062fbbba5349da1108d3c23cb330ca8a.zip | |
shader: SSA and dominance
Diffstat (limited to 'src/shader_recompiler/frontend/ir/basic_block.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/basic_block.cpp | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp index 0406726ad..e795618fc 100644 --- a/src/shader_recompiler/frontend/ir/basic_block.cpp +++ b/src/shader_recompiler/frontend/ir/basic_block.cpp | |||
| @@ -37,6 +37,10 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op, | |||
| 37 | return result_it; | 37 | return result_it; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | void Block::AddImmediatePredecessor(IR::Block* immediate_predecessor) { | ||
| 41 | imm_predecessors.push_back(immediate_predecessor); | ||
| 42 | } | ||
| 43 | |||
| 40 | u32 Block::LocationBegin() const noexcept { | 44 | u32 Block::LocationBegin() const noexcept { |
| 41 | return location_begin; | 45 | return location_begin; |
| 42 | } | 46 | } |
| @@ -53,6 +57,18 @@ const Block::InstructionList& Block::Instructions() const noexcept { | |||
| 53 | return instructions; | 57 | return instructions; |
| 54 | } | 58 | } |
| 55 | 59 | ||
| 60 | std::span<IR::Block* const> Block::ImmediatePredecessors() const noexcept { | ||
| 61 | return imm_predecessors; | ||
| 62 | } | ||
| 63 | |||
| 64 | static std::string BlockToIndex(const std::map<const Block*, size_t>& block_to_index, | ||
| 65 | Block* block) { | ||
| 66 | if (const auto it{block_to_index.find(block)}; it != block_to_index.end()) { | ||
| 67 | return fmt::format("{{Block ${}}}", it->second); | ||
| 68 | } | ||
| 69 | return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(block)); | ||
| 70 | } | ||
| 71 | |||
| 56 | static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index, | 72 | static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index, |
| 57 | const std::map<const Inst*, size_t>& inst_to_index, | 73 | const std::map<const Inst*, size_t>& inst_to_index, |
| 58 | const Value& arg) { | 74 | const Value& arg) { |
| @@ -60,10 +76,7 @@ static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_ind | |||
| 60 | return "<null>"; | 76 | return "<null>"; |
| 61 | } | 77 | } |
| 62 | if (arg.IsLabel()) { | 78 | if (arg.IsLabel()) { |
| 63 | if (const auto it{block_to_index.find(arg.Label())}; it != block_to_index.end()) { | 79 | return BlockToIndex(block_to_index, arg.Label()); |
| 64 | return fmt::format("{{Block ${}}}", it->second); | ||
| 65 | } | ||
| 66 | return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(arg.Label())); | ||
| 67 | } | 80 | } |
| 68 | if (!arg.IsImmediate()) { | 81 | if (!arg.IsImmediate()) { |
| 69 | if (const auto it{inst_to_index.find(arg.Inst())}; it != inst_to_index.end()) { | 82 | if (const auto it{inst_to_index.find(arg.Inst())}; it != inst_to_index.end()) { |
| @@ -115,16 +128,26 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>& | |||
| 115 | } else { | 128 | } else { |
| 116 | ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces | 129 | ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces |
| 117 | } | 130 | } |
| 118 | const size_t arg_count{NumArgsOf(op)}; | 131 | if (op == Opcode::Phi) { |
| 119 | for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) { | 132 | size_t val_index{0}; |
| 120 | const Value arg{inst.Arg(arg_index)}; | 133 | for (const auto& [phi_block, phi_val] : inst.PhiOperands()) { |
| 121 | ret += arg_index != 0 ? ", " : " "; | 134 | ret += val_index != 0 ? ", " : " "; |
| 122 | ret += ArgToIndex(block_to_index, inst_to_index, arg); | 135 | ret += fmt::format("[ {}, {} ]", ArgToIndex(block_to_index, inst_to_index, phi_val), |
| 123 | 136 | BlockToIndex(block_to_index, phi_block)); | |
| 124 | const Type actual_type{arg.Type()}; | 137 | ++val_index; |
| 125 | const Type expected_type{ArgTypeOf(op, arg_index)}; | 138 | } |
| 126 | if (!AreTypesCompatible(actual_type, expected_type)) { | 139 | } else { |
| 127 | ret += fmt::format("<type error: {} != {}>", actual_type, expected_type); | 140 | const size_t arg_count{NumArgsOf(op)}; |
| 141 | for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) { | ||
| 142 | const Value arg{inst.Arg(arg_index)}; | ||
| 143 | ret += arg_index != 0 ? ", " : " "; | ||
| 144 | ret += ArgToIndex(block_to_index, inst_to_index, arg); | ||
| 145 | |||
| 146 | const Type actual_type{arg.Type()}; | ||
| 147 | const Type expected_type{ArgTypeOf(op, arg_index)}; | ||
| 148 | if (!AreTypesCompatible(actual_type, expected_type)) { | ||
| 149 | ret += fmt::format("<type error: {} != {}>", actual_type, expected_type); | ||
| 150 | } | ||
| 128 | } | 151 | } |
| 129 | } | 152 | } |
| 130 | if (TypeOf(op) != Type::Void) { | 153 | if (TypeOf(op) != Type::Void) { |