summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/ir/basic_block.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/ir/basic_block.cpp')
-rw-r--r--src/shader_recompiler/frontend/ir/basic_block.cpp64
1 files changed, 47 insertions, 17 deletions
diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp
index da33ff6f1..b5616f394 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.cpp
+++ b/src/shader_recompiler/frontend/ir/basic_block.cpp
@@ -17,6 +17,8 @@ namespace Shader::IR {
17Block::Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end) 17Block::Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end)
18 : inst_pool{&inst_pool_}, location_begin{begin}, location_end{end} {} 18 : inst_pool{&inst_pool_}, location_begin{begin}, location_end{end} {}
19 19
20Block::Block(ObjectPool<Inst>& inst_pool_) : Block{inst_pool_, 0, 0} {}
21
20Block::~Block() = default; 22Block::~Block() = default;
21 23
22void Block::AppendNewInst(Opcode op, std::initializer_list<Value> args) { 24void Block::AppendNewInst(Opcode op, std::initializer_list<Value> args) {
@@ -38,8 +40,25 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
38 return result_it; 40 return result_it;
39} 41}
40 42
41void Block::AddImmediatePredecessor(IR::Block* immediate_predecessor) { 43void Block::SetBranches(Condition cond, Block* branch_true_, Block* branch_false_) {
42 imm_predecessors.push_back(immediate_predecessor); 44 branch_cond = cond;
45 branch_true = branch_true_;
46 branch_false = branch_false_;
47}
48
49void Block::SetBranch(Block* branch) {
50 branch_cond = Condition{true};
51 branch_true = branch;
52}
53
54void Block::SetReturn() {
55 branch_cond = Condition{true};
56 branch_true = nullptr;
57 branch_false = nullptr;
58}
59
60bool Block::IsVirtual() const noexcept {
61 return location_begin == location_end;
43} 62}
44 63
45u32 Block::LocationBegin() const noexcept { 64u32 Block::LocationBegin() const noexcept {
@@ -58,6 +77,12 @@ const Block::InstructionList& Block::Instructions() const noexcept {
58 return instructions; 77 return instructions;
59} 78}
60 79
80void Block::AddImmediatePredecessor(Block* block) {
81 if (std::ranges::find(imm_predecessors, block) == imm_predecessors.end()) {
82 imm_predecessors.push_back(block);
83 }
84}
85
61std::span<IR::Block* const> Block::ImmediatePredecessors() const noexcept { 86std::span<IR::Block* const> Block::ImmediatePredecessors() const noexcept {
62 return imm_predecessors; 87 return imm_predecessors;
63} 88}
@@ -70,8 +95,17 @@ static std::string BlockToIndex(const std::map<const Block*, size_t>& block_to_i
70 return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(block)); 95 return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(block));
71} 96}
72 97
98static size_t InstIndex(std::map<const Inst*, size_t>& inst_to_index, size_t& inst_index,
99 const Inst* inst) {
100 const auto [it, is_inserted]{inst_to_index.emplace(inst, inst_index + 1)};
101 if (is_inserted) {
102 ++inst_index;
103 }
104 return it->second;
105}
106
73static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index, 107static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index,
74 const std::map<const Inst*, size_t>& inst_to_index, 108 std::map<const Inst*, size_t>& inst_to_index, size_t& inst_index,
75 const Value& arg) { 109 const Value& arg) {
76 if (arg.IsEmpty()) { 110 if (arg.IsEmpty()) {
77 return "<null>"; 111 return "<null>";
@@ -80,10 +114,7 @@ static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_ind
80 return BlockToIndex(block_to_index, arg.Label()); 114 return BlockToIndex(block_to_index, arg.Label());
81 } 115 }
82 if (!arg.IsImmediate()) { 116 if (!arg.IsImmediate()) {
83 if (const auto it{inst_to_index.find(arg.Inst())}; it != inst_to_index.end()) { 117 return fmt::format("%{}", InstIndex(inst_to_index, inst_index, arg.Inst()));
84 return fmt::format("%{}", it->second);
85 }
86 return fmt::format("%<unknown inst {:016x}>", reinterpret_cast<u64>(arg.Inst()));
87 } 118 }
88 switch (arg.Type()) { 119 switch (arg.Type()) {
89 case Type::U1: 120 case Type::U1:
@@ -125,14 +156,14 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
125 const Opcode op{inst.Opcode()}; 156 const Opcode op{inst.Opcode()};
126 ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst)); 157 ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst));
127 if (TypeOf(op) != Type::Void) { 158 if (TypeOf(op) != Type::Void) {
128 ret += fmt::format("%{:<5} = {}", inst_index, op); 159 ret += fmt::format("%{:<5} = {}", InstIndex(inst_to_index, inst_index, &inst), op);
129 } else { 160 } else {
130 ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces 161 ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces
131 } 162 }
132 const size_t arg_count{NumArgsOf(op)}; 163 const size_t arg_count{inst.NumArgs()};
133 for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) { 164 for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) {
134 const Value arg{inst.Arg(arg_index)}; 165 const Value arg{inst.Arg(arg_index)};
135 const std::string arg_str{ArgToIndex(block_to_index, inst_to_index, arg)}; 166 const std::string arg_str{ArgToIndex(block_to_index, inst_to_index, inst_index, arg)};
136 ret += arg_index != 0 ? ", " : " "; 167 ret += arg_index != 0 ? ", " : " ";
137 if (op == Opcode::Phi) { 168 if (op == Opcode::Phi) {
138 ret += fmt::format("[ {}, {} ]", arg_index, 169 ret += fmt::format("[ {}, {} ]", arg_index,
@@ -140,10 +171,12 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
140 } else { 171 } else {
141 ret += arg_str; 172 ret += arg_str;
142 } 173 }
143 const Type actual_type{arg.Type()}; 174 if (op != Opcode::Phi) {
144 const Type expected_type{ArgTypeOf(op, arg_index)}; 175 const Type actual_type{arg.Type()};
145 if (!AreTypesCompatible(actual_type, expected_type)) { 176 const Type expected_type{ArgTypeOf(op, arg_index)};
146 ret += fmt::format("<type error: {} != {}>", actual_type, expected_type); 177 if (!AreTypesCompatible(actual_type, expected_type)) {
178 ret += fmt::format("<type error: {} != {}>", actual_type, expected_type);
179 }
147 } 180 }
148 } 181 }
149 if (TypeOf(op) != Type::Void) { 182 if (TypeOf(op) != Type::Void) {
@@ -151,9 +184,6 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
151 } else { 184 } else {
152 ret += '\n'; 185 ret += '\n';
153 } 186 }
154
155 inst_to_index.emplace(&inst, inst_index);
156 ++inst_index;
157 } 187 }
158 return ret; 188 return ret;
159} 189}