From 2ef696c85a37917102a9f869775180ab225f0d56 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 23 Sep 2019 11:15:09 -0400 Subject: Shader_IR: Implement BRX tracking. --- src/video_core/shader/control_flow.cpp | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) (limited to 'src/video_core/shader/control_flow.cpp') diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index 9d21f45de..70f758642 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -124,6 +124,111 @@ enum class ParseResult : u32 { AbnormalFlow, }; +struct BranchIndirectInfo { + u32 buffer{}; + u32 offset{}; + u32 entries{}; + s32 relative_position{}; +}; + +std::optional TrackBranchIndirectInfo(const CFGRebuildState& state, + u32 start_address, u32 current_position) { + const u32 shader_start = state.start; + u32 pos = current_position; + BranchIndirectInfo result{}; + u64 track_register = 0; + + // Step 0 Get BRX Info + const Instruction instr = {state.program_code[pos]}; + const auto opcode = OpCode::Decode(instr); + if (opcode->get().GetId() != OpCode::Id::BRX) { + return {}; + } + if (instr.brx.constant_buffer != 0) { + return {}; + } + track_register = instr.gpr8.Value(); + result.relative_position = instr.brx.GetBranchExtend(); + pos--; + bool found_track = false; + + // Step 1 Track LDC + while (pos >= shader_start) { + if (IsSchedInstruction(pos, shader_start)) { + pos--; + continue; + } + const Instruction instr = {state.program_code[pos]}; + const auto opcode = OpCode::Decode(instr); + if (opcode->get().GetId() == OpCode::Id::LD_C) { + if (instr.gpr0.Value() == track_register && + instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) { + result.buffer = instr.cbuf36.index; + result.offset = instr.cbuf36.GetOffset(); + track_register = instr.gpr8.Value(); + pos--; + found_track = true; + break; + } + } + pos--; + } + + if (!found_track) { + return {}; + } + found_track = false; + + // Step 2 Track SHL + while (pos >= shader_start) { + if (IsSchedInstruction(pos, shader_start)) { + pos--; + continue; + } + const Instruction instr = {state.program_code[pos]}; + const auto opcode = OpCode::Decode(instr); + if (opcode->get().GetId() == OpCode::Id::SHL_IMM) { + if (instr.gpr0.Value() == track_register) { + track_register = instr.gpr8.Value(); + pos--; + found_track = true; + break; + } + } + pos--; + } + + if (!found_track) { + return {}; + } + found_track = false; + + // Step 3 Track IMNMX + while (pos >= shader_start) { + if (IsSchedInstruction(pos, shader_start)) { + pos--; + continue; + } + const Instruction instr = {state.program_code[pos]}; + const auto opcode = OpCode::Decode(instr); + if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) { + if (instr.gpr0.Value() == track_register) { + track_register = instr.gpr8.Value(); + result.entries = instr.alu.GetSignedImm20_20(); + pos--; + found_track = true; + break; + } + } + pos--; + } + + if (!found_track) { + return {}; + } + return {result}; +} + std::pair ParseCode(CFGRebuildState& state, u32 address) { u32 offset = static_cast(address); const u32 end_address = static_cast(state.program_size / sizeof(Instruction)); @@ -298,6 +403,14 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) break; } case OpCode::Id::BRX: { + auto tmp = TrackBranchIndirectInfo(state, address, offset); + if (tmp) { + auto result = *tmp; + LOG_CRITICAL(HW_GPU, "Track Successful, BRX: buffer:{}, offset:{}, entries:{}", + result.buffer, result.offset, result.entries); + } else { + LOG_CRITICAL(HW_GPU, "Track Unsuccesful"); + } return {ParseResult::AbnormalFlow, parse_info}; } default: -- cgit v1.2.3 From acd64411342e70bd7e9f7156f62c3b1a609ac3c4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 23 Sep 2019 15:40:58 -0400 Subject: Shader_Cache: setup connection of ConstBufferLocker --- src/video_core/shader/control_flow.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/video_core/shader/control_flow.cpp') diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index 70f758642..dac2e4272 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -57,8 +57,8 @@ struct BlockInfo { struct CFGRebuildState { explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size, - const u32 start) - : start{start}, program_code{program_code}, program_size{program_size} {} + const u32 start, ConstBufferLocker& locker) + : start{start}, program_code{program_code}, program_size{program_size}, locker{locker} {} u32 start{}; std::vector block_info{}; @@ -72,6 +72,7 @@ struct CFGRebuildState { const ProgramCode& program_code; const std::size_t program_size; ASTManager* manager; + ConstBufferLocker& locker; }; enum class BlockCollision : u32 { None, Found, Inside }; @@ -214,7 +215,7 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) { if (instr.gpr0.Value() == track_register) { track_register = instr.gpr8.Value(); - result.entries = instr.alu.GetSignedImm20_20(); + result.entries = instr.alu.GetSignedImm20_20() + 1; pos--; found_track = true; break; @@ -406,8 +407,14 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) auto tmp = TrackBranchIndirectInfo(state, address, offset); if (tmp) { auto result = *tmp; - LOG_CRITICAL(HW_GPU, "Track Successful, BRX: buffer:{}, offset:{}, entries:{}", - result.buffer, result.offset, result.entries); + std::string entries{}; + for (u32 i = 0; i < result.entries; i++) { + auto k = locker.ObtainKey(result.buffer, result.offset + i * 4); + entries = entries + std::to_string(*k) + '\n'; + } + LOG_CRITICAL(HW_GPU, + "Track Successful, BRX: buffer:{}, offset:{}, entries:{}, inner:\n{}", + result.buffer, result.offset, result.entries, entries); } else { LOG_CRITICAL(HW_GPU, "Track Unsuccesful"); } @@ -588,14 +595,15 @@ void DecompileShader(CFGRebuildState& state) { std::unique_ptr ScanFlow(const ProgramCode& program_code, std::size_t program_size, u32 start_address, - const CompilerSettings& settings) { + const CompilerSettings& settings, + ConstBufferLocker& locker) { auto result_out = std::make_unique(); if (settings.depth == CompileDepth::BruteForce) { result_out->settings.depth = CompileDepth::BruteForce; return result_out; } - CFGRebuildState state{program_code, program_size, start_address}; + CFGRebuildState state{program_code, program_size, start_address, locker}; // Inspect Code and generate blocks state.labels.clear(); state.labels.emplace(start_address); -- cgit v1.2.3 From 8909f52166bf9c27d52b5a722efbd46d1a11e876 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 23 Sep 2019 22:55:25 -0400 Subject: Shader_IR: Implement Fast BRX and allow multi-branches in the CFG. --- src/video_core/shader/control_flow.cpp | 262 ++++++++++++++++++++------------- 1 file changed, 159 insertions(+), 103 deletions(-) (limited to 'src/video_core/shader/control_flow.cpp') diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index dac2e4272..d1c269ea7 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -35,14 +35,24 @@ struct BlockStack { std::stack pbk_stack{}; }; -struct BlockBranchInfo { - Condition condition{}; - s32 address{exit_branch}; - bool kill{}; - bool is_sync{}; - bool is_brk{}; - bool ignore{}; -}; +template +BlockBranchInfo MakeBranchInfo(Args&&... args) { + static_assert(std::is_convertible_v); + return std::make_shared(T(std::forward(args)...)); +} + +bool BlockBranchInfoAreEqual(BlockBranchInfo first, BlockBranchInfo second) { + return false; //(*first) == (*second); +} + +bool BlockBranchIsIgnored(BlockBranchInfo first) { + bool ignore = false; + if (std::holds_alternative(*first)) { + auto branch = std::get_if(first.get()); + ignore = branch->ignore; + } + return ignore; +} struct BlockInfo { u32 start{}; @@ -234,6 +244,7 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) u32 offset = static_cast(address); const u32 end_address = static_cast(state.program_size / sizeof(Instruction)); ParseInfo parse_info{}; + SingleBranch single_branch{}; const auto insert_label = [](CFGRebuildState& state, u32 address) { const auto pair = state.labels.emplace(address); @@ -246,13 +257,14 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) if (offset >= end_address) { // ASSERT_OR_EXECUTE can't be used, as it ignores the break ASSERT_MSG(false, "Shader passed the current limit!"); - parse_info.branch_info.address = exit_branch; - parse_info.branch_info.ignore = false; + + single_branch.address = exit_branch; + single_branch.ignore = false; break; } if (state.registered.count(offset) != 0) { - parse_info.branch_info.address = offset; - parse_info.branch_info.ignore = true; + single_branch.address = offset; + single_branch.ignore = true; break; } if (IsSchedInstruction(offset, state.start)) { @@ -269,24 +281,26 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) switch (opcode->get().GetId()) { case OpCode::Id::EXIT: { const auto pred_index = static_cast(instr.pred.pred_index); - parse_info.branch_info.condition.predicate = - GetPredicate(pred_index, instr.negate_pred != 0); - if (parse_info.branch_info.condition.predicate == Pred::NeverExecute) { + single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); + if (single_branch.condition.predicate == Pred::NeverExecute) { offset++; continue; } const ConditionCode cc = instr.flow_condition_code; - parse_info.branch_info.condition.cc = cc; + single_branch.condition.cc = cc; if (cc == ConditionCode::F) { offset++; continue; } - parse_info.branch_info.address = exit_branch; - parse_info.branch_info.kill = false; - parse_info.branch_info.is_sync = false; - parse_info.branch_info.is_brk = false; - parse_info.branch_info.ignore = false; + single_branch.address = exit_branch; + single_branch.kill = false; + single_branch.is_sync = false; + single_branch.is_brk = false; + single_branch.ignore = false; parse_info.end_address = offset; + parse_info.branch_info = MakeBranchInfo( + single_branch.condition, single_branch.address, single_branch.kill, + single_branch.is_sync, single_branch.is_brk, single_branch.ignore); return {ParseResult::ControlCaught, parse_info}; } @@ -295,99 +309,107 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) return {ParseResult::AbnormalFlow, parse_info}; } const auto pred_index = static_cast(instr.pred.pred_index); - parse_info.branch_info.condition.predicate = - GetPredicate(pred_index, instr.negate_pred != 0); - if (parse_info.branch_info.condition.predicate == Pred::NeverExecute) { + single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); + if (single_branch.condition.predicate == Pred::NeverExecute) { offset++; continue; } const ConditionCode cc = instr.flow_condition_code; - parse_info.branch_info.condition.cc = cc; + single_branch.condition.cc = cc; if (cc == ConditionCode::F) { offset++; continue; } const u32 branch_offset = offset + instr.bra.GetBranchTarget(); if (branch_offset == 0) { - parse_info.branch_info.address = exit_branch; + single_branch.address = exit_branch; } else { - parse_info.branch_info.address = branch_offset; + single_branch.address = branch_offset; } insert_label(state, branch_offset); - parse_info.branch_info.kill = false; - parse_info.branch_info.is_sync = false; - parse_info.branch_info.is_brk = false; - parse_info.branch_info.ignore = false; + single_branch.kill = false; + single_branch.is_sync = false; + single_branch.is_brk = false; + single_branch.ignore = false; parse_info.end_address = offset; + parse_info.branch_info = MakeBranchInfo( + single_branch.condition, single_branch.address, single_branch.kill, + single_branch.is_sync, single_branch.is_brk, single_branch.ignore); return {ParseResult::ControlCaught, parse_info}; } case OpCode::Id::SYNC: { const auto pred_index = static_cast(instr.pred.pred_index); - parse_info.branch_info.condition.predicate = - GetPredicate(pred_index, instr.negate_pred != 0); - if (parse_info.branch_info.condition.predicate == Pred::NeverExecute) { + single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); + if (single_branch.condition.predicate == Pred::NeverExecute) { offset++; continue; } const ConditionCode cc = instr.flow_condition_code; - parse_info.branch_info.condition.cc = cc; + single_branch.condition.cc = cc; if (cc == ConditionCode::F) { offset++; continue; } - parse_info.branch_info.address = unassigned_branch; - parse_info.branch_info.kill = false; - parse_info.branch_info.is_sync = true; - parse_info.branch_info.is_brk = false; - parse_info.branch_info.ignore = false; + single_branch.address = unassigned_branch; + single_branch.kill = false; + single_branch.is_sync = true; + single_branch.is_brk = false; + single_branch.ignore = false; parse_info.end_address = offset; + parse_info.branch_info = MakeBranchInfo( + single_branch.condition, single_branch.address, single_branch.kill, + single_branch.is_sync, single_branch.is_brk, single_branch.ignore); return {ParseResult::ControlCaught, parse_info}; } case OpCode::Id::BRK: { const auto pred_index = static_cast(instr.pred.pred_index); - parse_info.branch_info.condition.predicate = - GetPredicate(pred_index, instr.negate_pred != 0); - if (parse_info.branch_info.condition.predicate == Pred::NeverExecute) { + single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); + if (single_branch.condition.predicate == Pred::NeverExecute) { offset++; continue; } const ConditionCode cc = instr.flow_condition_code; - parse_info.branch_info.condition.cc = cc; + single_branch.condition.cc = cc; if (cc == ConditionCode::F) { offset++; continue; } - parse_info.branch_info.address = unassigned_branch; - parse_info.branch_info.kill = false; - parse_info.branch_info.is_sync = false; - parse_info.branch_info.is_brk = true; - parse_info.branch_info.ignore = false; + single_branch.address = unassigned_branch; + single_branch.kill = false; + single_branch.is_sync = false; + single_branch.is_brk = true; + single_branch.ignore = false; parse_info.end_address = offset; + parse_info.branch_info = MakeBranchInfo( + single_branch.condition, single_branch.address, single_branch.kill, + single_branch.is_sync, single_branch.is_brk, single_branch.ignore); return {ParseResult::ControlCaught, parse_info}; } case OpCode::Id::KIL: { const auto pred_index = static_cast(instr.pred.pred_index); - parse_info.branch_info.condition.predicate = - GetPredicate(pred_index, instr.negate_pred != 0); - if (parse_info.branch_info.condition.predicate == Pred::NeverExecute) { + single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); + if (single_branch.condition.predicate == Pred::NeverExecute) { offset++; continue; } const ConditionCode cc = instr.flow_condition_code; - parse_info.branch_info.condition.cc = cc; + single_branch.condition.cc = cc; if (cc == ConditionCode::F) { offset++; continue; } - parse_info.branch_info.address = exit_branch; - parse_info.branch_info.kill = true; - parse_info.branch_info.is_sync = false; - parse_info.branch_info.is_brk = false; - parse_info.branch_info.ignore = false; + single_branch.address = exit_branch; + single_branch.kill = true; + single_branch.is_sync = false; + single_branch.is_brk = false; + single_branch.ignore = false; parse_info.end_address = offset; + parse_info.branch_info = MakeBranchInfo( + single_branch.condition, single_branch.address, single_branch.kill, + single_branch.is_sync, single_branch.is_brk, single_branch.ignore); return {ParseResult::ControlCaught, parse_info}; } @@ -407,16 +429,25 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) auto tmp = TrackBranchIndirectInfo(state, address, offset); if (tmp) { auto result = *tmp; - std::string entries{}; + std::vector branches{}; + s32 pc_target = offset + result.relative_position; for (u32 i = 0; i < result.entries; i++) { - auto k = locker.ObtainKey(result.buffer, result.offset + i * 4); - entries = entries + std::to_string(*k) + '\n'; + auto k = state.locker.ObtainKey(result.buffer, result.offset + i * 4); + if (!k) { + return {ParseResult::AbnormalFlow, parse_info}; + } + u32 value = *k; + u32 target = static_cast((value >> 3) + pc_target); + insert_label(state, target); + branches.emplace_back(value, target); } - LOG_CRITICAL(HW_GPU, - "Track Successful, BRX: buffer:{}, offset:{}, entries:{}, inner:\n{}", - result.buffer, result.offset, result.entries, entries); + parse_info.end_address = offset; + parse_info.branch_info = + MakeBranchInfo(static_cast(instr.gpr8.Value()), branches); + + return {ParseResult::ControlCaught, parse_info}; } else { - LOG_CRITICAL(HW_GPU, "Track Unsuccesful"); + LOG_WARNING(HW_GPU, "BRX Track Unsuccesful"); } return {ParseResult::AbnormalFlow, parse_info}; } @@ -426,10 +457,13 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) offset++; } - parse_info.branch_info.kill = false; - parse_info.branch_info.is_sync = false; - parse_info.branch_info.is_brk = false; + single_branch.kill = false; + single_branch.is_sync = false; + single_branch.is_brk = false; parse_info.end_address = offset - 1; + parse_info.branch_info = MakeBranchInfo( + single_branch.condition, single_branch.address, single_branch.kill, single_branch.is_sync, + single_branch.is_brk, single_branch.ignore); return {ParseResult::BlockEnd, parse_info}; } @@ -453,9 +487,10 @@ bool TryInspectAddress(CFGRebuildState& state) { BlockInfo& current_block = state.block_info[block_index]; current_block.end = address - 1; new_block.branch = current_block.branch; - BlockBranchInfo forward_branch{}; - forward_branch.address = address; - forward_branch.ignore = true; + BlockBranchInfo forward_branch = MakeBranchInfo(); + auto branch = std::get_if(forward_branch.get()); + branch->address = address; + branch->ignore = true; current_block.branch = forward_branch; return true; } @@ -470,12 +505,15 @@ bool TryInspectAddress(CFGRebuildState& state) { BlockInfo& block_info = CreateBlockInfo(state, address, parse_info.end_address); block_info.branch = parse_info.branch_info; - if (parse_info.branch_info.condition.IsUnconditional()) { + if (std::holds_alternative(*block_info.branch)) { + auto branch = std::get_if(block_info.branch.get()); + if (branch->condition.IsUnconditional()) { + return true; + } + const u32 fallthrough_address = parse_info.end_address + 1; + state.inspect_queries.push_front(fallthrough_address); return true; } - - const u32 fallthrough_address = parse_info.end_address + 1; - state.inspect_queries.push_front(fallthrough_address); return true; } @@ -513,31 +551,41 @@ bool TryQuery(CFGRebuildState& state) { state.queries.pop_front(); gather_labels(q2.ssy_stack, state.ssy_labels, block); gather_labels(q2.pbk_stack, state.pbk_labels, block); - if (!block.branch.condition.IsUnconditional()) { - q2.address = block.end + 1; - state.queries.push_back(q2); - } + if (std::holds_alternative(*block.branch)) { + auto branch = std::get_if(block.branch.get()); + if (!branch->condition.IsUnconditional()) { + q2.address = block.end + 1; + state.queries.push_back(q2); + } - Query conditional_query{q2}; - if (block.branch.is_sync) { - if (block.branch.address == unassigned_branch) { - block.branch.address = conditional_query.ssy_stack.top(); + Query conditional_query{q2}; + if (branch->is_sync) { + if (branch->address == unassigned_branch) { + branch->address = conditional_query.ssy_stack.top(); + } + conditional_query.ssy_stack.pop(); } - conditional_query.ssy_stack.pop(); - } - if (block.branch.is_brk) { - if (block.branch.address == unassigned_branch) { - block.branch.address = conditional_query.pbk_stack.top(); + if (branch->is_brk) { + if (branch->address == unassigned_branch) { + branch->address = conditional_query.pbk_stack.top(); + } + conditional_query.pbk_stack.pop(); } - conditional_query.pbk_stack.pop(); + conditional_query.address = branch->address; + state.queries.push_back(std::move(conditional_query)); + return true; + } + auto multi_branch = std::get_if(block.branch.get()); + for (auto& branch_case : multi_branch->branches) { + Query conditional_query{q2}; + conditional_query.address = branch_case.address; + state.queries.push_back(std::move(conditional_query)); } - conditional_query.address = block.branch.address; - state.queries.push_back(std::move(conditional_query)); return true; } } // Anonymous namespace -void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch) { +void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) { const auto get_expr = ([&](const Condition& cond) -> Expr { Expr result{}; if (cond.cc != ConditionCode::T) { @@ -564,15 +612,24 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch) { } return MakeExpr(true); }); - if (branch.address < 0) { - if (branch.kill) { - mm.InsertReturn(get_expr(branch.condition), true); + if (std::holds_alternative(*branch_info)) { + auto branch = std::get_if(branch_info.get()); + if (branch->address < 0) { + if (branch->kill) { + mm.InsertReturn(get_expr(branch->condition), true); + return; + } + mm.InsertReturn(get_expr(branch->condition), false); return; } - mm.InsertReturn(get_expr(branch.condition), false); + mm.InsertGoto(get_expr(branch->condition), branch->address); return; } - mm.InsertGoto(get_expr(branch.condition), branch.address); + auto multi_branch = std::get_if(branch_info.get()); + for (auto& branch_case : multi_branch->branches) { + mm.InsertGoto(MakeExpr(multi_branch->gpr, branch_case.cmp_value), + branch_case.address); + } } void DecompileShader(CFGRebuildState& state) { @@ -584,9 +641,10 @@ void DecompileShader(CFGRebuildState& state) { if (state.labels.count(block.start) != 0) { state.manager->InsertLabel(block.start); } - u32 end = block.branch.ignore ? block.end + 1 : block.end; + const bool ignore = BlockBranchIsIgnored(block.branch); + u32 end = ignore ? block.end + 1 : block.end; state.manager->InsertBlock(block.start, end); - if (!block.branch.ignore) { + if (!ignore) { InsertBranch(*state.manager, block.branch); } } @@ -668,11 +726,9 @@ std::unique_ptr ScanFlow(const ProgramCode& program_code, ShaderBlock new_block{}; new_block.start = block.start; new_block.end = block.end; - new_block.ignore_branch = block.branch.ignore; + new_block.ignore_branch = BlockBranchIsIgnored(block.branch); if (!new_block.ignore_branch) { - new_block.branch.cond = block.branch.condition; - new_block.branch.kills = block.branch.kill; - new_block.branch.address = block.branch.address; + new_block.branch = block.branch; } result_out->end = std::max(result_out->end, block.end); result_out->blocks.push_back(new_block); -- cgit v1.2.3 From 7b81ba4d8a9805f808fcc60a0905ac74d293b2ee Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 24 Sep 2019 23:34:18 -0300 Subject: gl_shader_decompiler: Move entries to a separate function --- src/video_core/shader/control_flow.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src/video_core/shader/control_flow.cpp') diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index d1c269ea7..6c698bcff 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -66,10 +66,11 @@ struct BlockInfo { }; struct CFGRebuildState { - explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size, - const u32 start, ConstBufferLocker& locker) - : start{start}, program_code{program_code}, program_size{program_size}, locker{locker} {} + explicit CFGRebuildState(const ProgramCode& program_code, u32 start, ConstBufferLocker& locker) + : program_code{program_code}, start{start}, locker{locker} {} + const ProgramCode& program_code; + ConstBufferLocker& locker; u32 start{}; std::vector block_info{}; std::list inspect_queries{}; @@ -79,10 +80,7 @@ struct CFGRebuildState { std::map ssy_labels{}; std::map pbk_labels{}; std::unordered_map stacks{}; - const ProgramCode& program_code; - const std::size_t program_size; ASTManager* manager; - ConstBufferLocker& locker; }; enum class BlockCollision : u32 { None, Found, Inside }; @@ -242,7 +240,7 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& std::pair ParseCode(CFGRebuildState& state, u32 address) { u32 offset = static_cast(address); - const u32 end_address = static_cast(state.program_size / sizeof(Instruction)); + const u32 end_address = static_cast(state.program_code.size()); ParseInfo parse_info{}; SingleBranch single_branch{}; @@ -583,6 +581,7 @@ bool TryQuery(CFGRebuildState& state) { } return true; } + } // Anonymous namespace void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) { @@ -651,8 +650,7 @@ void DecompileShader(CFGRebuildState& state) { state.manager->Decompile(); } -std::unique_ptr ScanFlow(const ProgramCode& program_code, - std::size_t program_size, u32 start_address, +std::unique_ptr ScanFlow(const ProgramCode& program_code, u32 start_address, const CompilerSettings& settings, ConstBufferLocker& locker) { auto result_out = std::make_unique(); @@ -661,7 +659,7 @@ std::unique_ptr ScanFlow(const ProgramCode& program_code, return result_out; } - CFGRebuildState state{program_code, program_size, start_address, locker}; + CFGRebuildState state{program_code, start_address, locker}; // Inspect Code and generate blocks state.labels.clear(); state.labels.emplace(start_address); -- cgit v1.2.3 From be856a38d6b0c7c90c861baf3204ac48a108f3d2 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 17 Oct 2019 10:35:16 -0400 Subject: Shader_IR: Address Feedback. --- src/video_core/shader/control_flow.cpp | 46 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'src/video_core/shader/control_flow.cpp') diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index 6c698bcff..d47c63d9f 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -41,14 +41,10 @@ BlockBranchInfo MakeBranchInfo(Args&&... args) { return std::make_shared(T(std::forward(args)...)); } -bool BlockBranchInfoAreEqual(BlockBranchInfo first, BlockBranchInfo second) { - return false; //(*first) == (*second); -} - bool BlockBranchIsIgnored(BlockBranchInfo first) { bool ignore = false; if (std::holds_alternative(*first)) { - auto branch = std::get_if(first.get()); + const auto branch = std::get_if(first.get()); ignore = branch->ignore; } return ignore; @@ -151,10 +147,10 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& const Instruction instr = {state.program_code[pos]}; const auto opcode = OpCode::Decode(instr); if (opcode->get().GetId() != OpCode::Id::BRX) { - return {}; + return std::nullopt; } if (instr.brx.constant_buffer != 0) { - return {}; + return std::nullopt; } track_register = instr.gpr8.Value(); result.relative_position = instr.brx.GetBranchExtend(); @@ -172,8 +168,8 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& if (opcode->get().GetId() == OpCode::Id::LD_C) { if (instr.gpr0.Value() == track_register && instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) { - result.buffer = instr.cbuf36.index; - result.offset = instr.cbuf36.GetOffset(); + result.buffer = instr.cbuf36.index.Value(); + result.offset = static_cast(instr.cbuf36.GetOffset()); track_register = instr.gpr8.Value(); pos--; found_track = true; @@ -184,7 +180,7 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& } if (!found_track) { - return {}; + return std::nullopt; } found_track = false; @@ -194,7 +190,7 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& pos--; continue; } - const Instruction instr = {state.program_code[pos]}; + const Instruction instr = state.program_code[pos]; const auto opcode = OpCode::Decode(instr); if (opcode->get().GetId() == OpCode::Id::SHL_IMM) { if (instr.gpr0.Value() == track_register) { @@ -208,7 +204,7 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& } if (!found_track) { - return {}; + return std::nullopt; } found_track = false; @@ -218,7 +214,7 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& pos--; continue; } - const Instruction instr = {state.program_code[pos]}; + const Instruction instr = state.program_code[pos]; const auto opcode = OpCode::Decode(instr); if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) { if (instr.gpr0.Value() == track_register) { @@ -233,9 +229,9 @@ std::optional TrackBranchIndirectInfo(const CFGRebuildState& } if (!found_track) { - return {}; + return std::nullopt; } - return {result}; + return result; } std::pair ParseCode(CFGRebuildState& state, u32 address) { @@ -440,8 +436,8 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) branches.emplace_back(value, target); } parse_info.end_address = offset; - parse_info.branch_info = - MakeBranchInfo(static_cast(instr.gpr8.Value()), branches); + parse_info.branch_info = MakeBranchInfo( + static_cast(instr.gpr8.Value()), std::move(branches)); return {ParseResult::ControlCaught, parse_info}; } else { @@ -486,7 +482,7 @@ bool TryInspectAddress(CFGRebuildState& state) { current_block.end = address - 1; new_block.branch = current_block.branch; BlockBranchInfo forward_branch = MakeBranchInfo(); - auto branch = std::get_if(forward_branch.get()); + const auto branch = std::get_if(forward_branch.get()); branch->address = address; branch->ignore = true; current_block.branch = forward_branch; @@ -504,7 +500,7 @@ bool TryInspectAddress(CFGRebuildState& state) { BlockInfo& block_info = CreateBlockInfo(state, address, parse_info.end_address); block_info.branch = parse_info.branch_info; if (std::holds_alternative(*block_info.branch)) { - auto branch = std::get_if(block_info.branch.get()); + const auto branch = std::get_if(block_info.branch.get()); if (branch->condition.IsUnconditional()) { return true; } @@ -550,7 +546,7 @@ bool TryQuery(CFGRebuildState& state) { gather_labels(q2.ssy_stack, state.ssy_labels, block); gather_labels(q2.pbk_stack, state.pbk_labels, block); if (std::holds_alternative(*block.branch)) { - auto branch = std::get_if(block.branch.get()); + const auto branch = std::get_if(block.branch.get()); if (!branch->condition.IsUnconditional()) { q2.address = block.end + 1; state.queries.push_back(q2); @@ -573,8 +569,8 @@ bool TryQuery(CFGRebuildState& state) { state.queries.push_back(std::move(conditional_query)); return true; } - auto multi_branch = std::get_if(block.branch.get()); - for (auto& branch_case : multi_branch->branches) { + const auto multi_branch = std::get_if(block.branch.get()); + for (const auto& branch_case : multi_branch->branches) { Query conditional_query{q2}; conditional_query.address = branch_case.address; state.queries.push_back(std::move(conditional_query)); @@ -612,7 +608,7 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) { return MakeExpr(true); }); if (std::holds_alternative(*branch_info)) { - auto branch = std::get_if(branch_info.get()); + const auto branch = std::get_if(branch_info.get()); if (branch->address < 0) { if (branch->kill) { mm.InsertReturn(get_expr(branch->condition), true); @@ -624,8 +620,8 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) { mm.InsertGoto(get_expr(branch->condition), branch->address); return; } - auto multi_branch = std::get_if(branch_info.get()); - for (auto& branch_case : multi_branch->branches) { + const auto multi_branch = std::get_if(branch_info.get()); + for (const auto& branch_case : multi_branch->branches) { mm.InsertGoto(MakeExpr(multi_branch->gpr, branch_case.cmp_value), branch_case.address); } -- cgit v1.2.3