shader_ir: Remove the old scanner.
This commit is contained in:
parent
8af6e6a052
commit
c218ae4b02
|
@ -22,20 +22,6 @@ using Tegra::Shader::OpCode;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Merges exit method of two parallel branches.
|
|
||||||
constexpr ExitMethod ParallelExit(ExitMethod a, ExitMethod b) {
|
|
||||||
if (a == ExitMethod::Undetermined) {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
if (b == ExitMethod::Undetermined) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
if (a == b) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return ExitMethod::Conditional;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the instruction at the specified offset is a 'sched' instruction.
|
* Returns whether the instruction at the specified offset is a 'sched' instruction.
|
||||||
* Sched instructions always appear before a sequence of 3 instructions.
|
* Sched instructions always appear before a sequence of 3 instructions.
|
||||||
|
@ -79,58 +65,6 @@ void ShaderIR::Decode() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitMethod ShaderIR::Scan(u32 begin, u32 end, std::set<u32>& labels) {
|
|
||||||
const auto [iter, inserted] =
|
|
||||||
exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined);
|
|
||||||
ExitMethod& exit_method = iter->second;
|
|
||||||
if (!inserted)
|
|
||||||
return exit_method;
|
|
||||||
|
|
||||||
for (u32 offset = begin; offset != end && offset != MAX_PROGRAM_LENGTH; ++offset) {
|
|
||||||
coverage_begin = std::min(coverage_begin, offset);
|
|
||||||
coverage_end = std::max(coverage_end, offset + 1);
|
|
||||||
|
|
||||||
const Instruction instr = {program_code[offset]};
|
|
||||||
const auto opcode = OpCode::Decode(instr);
|
|
||||||
if (!opcode)
|
|
||||||
continue;
|
|
||||||
switch (opcode->get().GetId()) {
|
|
||||||
case OpCode::Id::EXIT: {
|
|
||||||
// The EXIT instruction can be predicated, which means that the shader can conditionally
|
|
||||||
// end on this instruction. We have to consider the case where the condition is not met
|
|
||||||
// and check the exit method of that other basic block.
|
|
||||||
using Tegra::Shader::Pred;
|
|
||||||
if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
|
|
||||||
return exit_method = ExitMethod::AlwaysEnd;
|
|
||||||
} else {
|
|
||||||
const ExitMethod not_met = Scan(offset + 1, end, labels);
|
|
||||||
return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case OpCode::Id::BRA: {
|
|
||||||
const u32 target = offset + instr.bra.GetBranchTarget();
|
|
||||||
labels.insert(target);
|
|
||||||
const ExitMethod no_jmp = Scan(offset + 1, end, labels);
|
|
||||||
const ExitMethod jmp = Scan(target, end, labels);
|
|
||||||
return exit_method = ParallelExit(no_jmp, jmp);
|
|
||||||
}
|
|
||||||
case OpCode::Id::SSY:
|
|
||||||
case OpCode::Id::PBK: {
|
|
||||||
// The SSY and PBK use a similar encoding as the BRA instruction.
|
|
||||||
UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
|
|
||||||
"Constant buffer branching is not supported");
|
|
||||||
const u32 target = offset + instr.bra.GetBranchTarget();
|
|
||||||
labels.insert(target);
|
|
||||||
// Continue scanning for an exit method.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exit_method = ExitMethod::AlwaysReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) {
|
NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) {
|
||||||
NodeBlock basic_block;
|
NodeBlock basic_block;
|
||||||
for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) {
|
for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) {
|
||||||
|
|
|
@ -26,14 +26,6 @@ using ProgramCode = std::vector<u64>;
|
||||||
|
|
||||||
constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
|
constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
|
||||||
|
|
||||||
/// Describes the behaviour of code path of a given entry point and a return point.
|
|
||||||
enum class ExitMethod {
|
|
||||||
Undetermined, ///< Internal value. Only occur when analyzing JMP loop.
|
|
||||||
AlwaysReturn, ///< All code paths reach the return point.
|
|
||||||
Conditional, ///< Code path reaches the return point or an END instruction conditionally.
|
|
||||||
AlwaysEnd, ///< All code paths reach a END instruction.
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConstBuffer {
|
class ConstBuffer {
|
||||||
public:
|
public:
|
||||||
explicit ConstBuffer(u32 max_offset, bool is_indirect)
|
explicit ConstBuffer(u32 max_offset, bool is_indirect)
|
||||||
|
@ -132,8 +124,6 @@ public:
|
||||||
private:
|
private:
|
||||||
void Decode();
|
void Decode();
|
||||||
|
|
||||||
ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels);
|
|
||||||
|
|
||||||
NodeBlock DecodeRange(u32 begin, u32 end);
|
NodeBlock DecodeRange(u32 begin, u32 end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -329,7 +319,6 @@ private:
|
||||||
|
|
||||||
u32 coverage_begin{};
|
u32 coverage_begin{};
|
||||||
u32 coverage_end{};
|
u32 coverage_end{};
|
||||||
std::map<std::pair<u32, u32>, ExitMethod> exit_method_map;
|
|
||||||
|
|
||||||
std::map<u32, NodeBlock> basic_blocks;
|
std::map<u32, NodeBlock> basic_blocks;
|
||||||
NodeBlock global_code;
|
NodeBlock global_code;
|
||||||
|
|
Reference in New Issue