mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: preserve folded control-flow values
This commit is contained in:
@@ -729,10 +729,7 @@ bool TryRecompile(std::span<const uint32_t> code, const CompileOptions& options,
|
|||||||
ir.blocks.clear();
|
ir.blocks.clear();
|
||||||
IR::RewriteToSsa(ir.values->blocks);
|
IR::RewriteToSsa(ir.values->blocks);
|
||||||
IR::ConstantPropagationPass(ir.values->blocks);
|
IR::ConstantPropagationPass(ir.values->blocks);
|
||||||
for (auto& info: ir.values->block_info) {
|
IR::ResolveControlFlowIdentities(*ir.values);
|
||||||
info.condition = info.condition.Resolve();
|
|
||||||
info.indirect_target = info.indirect_target.Resolve();
|
|
||||||
}
|
|
||||||
IR::RemoveIdentities(ir.values->blocks);
|
IR::RemoveIdentities(ir.values->blocks);
|
||||||
IR::EliminateDeadCode(ir.values->blocks);
|
IR::EliminateDeadCode(ir.values->blocks);
|
||||||
const auto read_lane_stats = IR::EliminateReadLane(*ir.values, ir.wave_size);
|
const auto read_lane_stats = IR::EliminateReadLane(*ir.values, ir.wave_size);
|
||||||
@@ -740,6 +737,7 @@ bool TryRecompile(std::span<const uint32_t> code, const CompileOptions& options,
|
|||||||
LOGF("%s read-lane elimination: reads=%" PRIu32 "\n", GetDumpLabel(options),
|
LOGF("%s read-lane elimination: reads=%" PRIu32 "\n", GetDumpLabel(options),
|
||||||
read_lane_stats.rewritten_reads);
|
read_lane_stats.rewritten_reads);
|
||||||
IR::ConstantPropagationPass(ir.values->blocks);
|
IR::ConstantPropagationPass(ir.values->blocks);
|
||||||
|
IR::ResolveControlFlowIdentities(*ir.values);
|
||||||
IR::RemoveIdentities(ir.values->blocks);
|
IR::RemoveIdentities(ir.values->blocks);
|
||||||
IR::EliminateDeadCode(ir.values->blocks);
|
IR::EliminateDeadCode(ir.values->blocks);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -591,6 +591,13 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResolveControlFlowIdentities(ValueProgram& program) {
|
||||||
|
for (auto& info: program.block_info) {
|
||||||
|
info.condition = info.condition.Resolve();
|
||||||
|
info.indirect_target = info.indirect_target.Resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string ValueProgramToString(const ValueProgram& program) {
|
std::string ValueProgramToString(const ValueProgram& program) {
|
||||||
std::map<const Inst*, size_t> ids;
|
std::map<const Inst*, size_t> ids;
|
||||||
size_t next_id = 1;
|
size_t next_id = 1;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ struct ValueProgram {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::string* error);
|
bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::string* error);
|
||||||
|
void ResolveControlFlowIdentities(ValueProgram& program);
|
||||||
bool EquivalentValue(const ValueProgram& program, Value left, Value right);
|
bool EquivalentValue(const ValueProgram& program, Value left, Value right);
|
||||||
Value ResolveInvariantPhi(const ValueProgram& program, Value value);
|
Value ResolveInvariantPhi(const ValueProgram& program, Value value);
|
||||||
std::string ValueProgramToString(const ValueProgram& program);
|
std::string ValueProgramToString(const ValueProgram& program);
|
||||||
|
|||||||
@@ -402,6 +402,47 @@ void TestOptimizationPipeline() {
|
|||||||
"elimination regressed");
|
"elimination regressed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestControlFlowValueSurvivesReadLaneFolding() {
|
||||||
|
Fixture fixture(3);
|
||||||
|
auto *entry = fixture.program.values->blocks[0];
|
||||||
|
auto *taken = fixture.program.values->blocks[1];
|
||||||
|
auto *other = fixture.program.values->blocks[2];
|
||||||
|
entry->AddBranch(taken);
|
||||||
|
entry->AddBranch(other);
|
||||||
|
|
||||||
|
auto &entry_info = fixture.program.values->block_info[0];
|
||||||
|
entry_info.terminator.kind =
|
||||||
|
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||||
|
entry_info.terminator.true_block = 1;
|
||||||
|
entry_info.terminator.false_block = 2;
|
||||||
|
fixture.program.values->block_info[1].terminator.kind =
|
||||||
|
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||||
|
fixture.program.values->block_info[2].terminator.kind =
|
||||||
|
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||||
|
|
||||||
|
const auto undef = fixture.Emit(ValueOpcode::UndefU32);
|
||||||
|
const auto write = fixture.Emit(
|
||||||
|
ValueOpcode::WriteLane, {undef, Value(42u), Value(5u)});
|
||||||
|
const auto read =
|
||||||
|
fixture.Emit(ValueOpcode::ReadLane, {write, Value(5u)});
|
||||||
|
entry_info.condition =
|
||||||
|
fixture.Emit(ValueOpcode::IEqual32, {read, Value(42u)});
|
||||||
|
fixture.Emit(ValueOpcode::Reference, {entry_info.condition});
|
||||||
|
|
||||||
|
Check(EliminateReadLane(*fixture.program.values, 64).rewritten_reads == 1,
|
||||||
|
"control-flow fixture did not eliminate its fixed-lane read");
|
||||||
|
ConstantPropagationPass(fixture.program.values->blocks);
|
||||||
|
ResolveControlFlowIdentities(*fixture.program.values);
|
||||||
|
RemoveIdentities(fixture.program.values->blocks);
|
||||||
|
EliminateDeadCode(fixture.program.values->blocks);
|
||||||
|
|
||||||
|
std::string error;
|
||||||
|
Check(entry_info.condition == Value(true) &&
|
||||||
|
ValidateValueProgram(*fixture.program.values, true, &error),
|
||||||
|
error.empty() ? "folded branch condition did not survive identity removal"
|
||||||
|
: error.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void TestUndefinedRuntimeValueFails() {
|
void TestUndefinedRuntimeValueFails() {
|
||||||
Fixture fixture;
|
Fixture fixture;
|
||||||
const auto undef = fixture.Emit(ValueOpcode::UndefU32);
|
const auto undef = fixture.Emit(ValueOpcode::UndefU32);
|
||||||
@@ -443,6 +484,7 @@ int main() {
|
|||||||
TestConstantBufferBounds();
|
TestConstantBufferBounds();
|
||||||
TestReadLaneElimination();
|
TestReadLaneElimination();
|
||||||
TestOptimizationPipeline();
|
TestOptimizationPipeline();
|
||||||
|
TestControlFlowValueSurvivesReadLaneFolding();
|
||||||
TestUndefinedRuntimeValueFails();
|
TestUndefinedRuntimeValueFails();
|
||||||
std::cout << "TypedValuePlanningTests: all cases passed\n";
|
std::cout << "TypedValuePlanningTests: all cases passed\n";
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -10498,16 +10498,14 @@ bool LowerTypedPlanning(const uint32_t *code, uint32_t words,
|
|||||||
ir.blocks.clear();
|
ir.blocks.clear();
|
||||||
ShaderRecompiler::IR::RewriteToSsa(ir.values->blocks);
|
ShaderRecompiler::IR::RewriteToSsa(ir.values->blocks);
|
||||||
ShaderRecompiler::IR::ConstantPropagationPass(ir.values->blocks);
|
ShaderRecompiler::IR::ConstantPropagationPass(ir.values->blocks);
|
||||||
for (auto &info : ir.values->block_info) {
|
ShaderRecompiler::IR::ResolveControlFlowIdentities(*ir.values);
|
||||||
info.condition = info.condition.Resolve();
|
|
||||||
info.indirect_target = info.indirect_target.Resolve();
|
|
||||||
}
|
|
||||||
ShaderRecompiler::IR::RemoveIdentities(ir.values->blocks);
|
ShaderRecompiler::IR::RemoveIdentities(ir.values->blocks);
|
||||||
ShaderRecompiler::IR::EliminateDeadCode(ir.values->blocks);
|
ShaderRecompiler::IR::EliminateDeadCode(ir.values->blocks);
|
||||||
const auto read_lane =
|
const auto read_lane =
|
||||||
ShaderRecompiler::IR::EliminateReadLane(*ir.values, ir.wave_size);
|
ShaderRecompiler::IR::EliminateReadLane(*ir.values, ir.wave_size);
|
||||||
if (read_lane.rewritten_reads != 0) {
|
if (read_lane.rewritten_reads != 0) {
|
||||||
ShaderRecompiler::IR::ConstantPropagationPass(ir.values->blocks);
|
ShaderRecompiler::IR::ConstantPropagationPass(ir.values->blocks);
|
||||||
|
ShaderRecompiler::IR::ResolveControlFlowIdentities(*ir.values);
|
||||||
ShaderRecompiler::IR::RemoveIdentities(ir.values->blocks);
|
ShaderRecompiler::IR::RemoveIdentities(ir.values->blocks);
|
||||||
ShaderRecompiler::IR::EliminateDeadCode(ir.values->blocks);
|
ShaderRecompiler::IR::EliminateDeadCode(ir.values->blocks);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user