mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
shader: own control flow on IR blocks with direct targets
This commit is contained in:
@@ -27,7 +27,7 @@ AddValueBlock(Libs::Graphics::ShaderRecompiler::IR::Program &program) {
|
||||
auto block = std::make_unique<Block>();
|
||||
auto *result = block.get();
|
||||
program.blocks.push_back(result);
|
||||
program.block_info.push_back({.id = 0});
|
||||
result->id = static_cast<uint32_t>(program.blocks.size() - 1u);
|
||||
program.block_storage.push_back(std::move(block));
|
||||
return *result;
|
||||
}
|
||||
@@ -462,16 +462,16 @@ void TestWrittenDescriptorUsesStrictReaderOnce() {
|
||||
{Value(&offset), Value(4u)});
|
||||
auto &store_block = AddValueBlock(program);
|
||||
AddValueBlock(program);
|
||||
program.block_info[0].condition = Value(&condition);
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->condition = Value(&condition);
|
||||
program.blocks[0]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[0].terminator.false_block = 2;
|
||||
program.block_info[1].id = 1;
|
||||
program.block_info[1].terminator.kind =
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[0]->terminator.false_block = program.blocks[2];
|
||||
program.blocks[1]->id = 1;
|
||||
program.blocks[1]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
program.block_info[2].id = 2;
|
||||
program.block_info[2].terminator.kind =
|
||||
program.blocks[2]->id = 2;
|
||||
program.blocks[2]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
program.memory_info.push_back({.kind = ResourceKind::Buffer, .resource = 0});
|
||||
auto &output = store_block.AppendNewInst(ValueOpcode::GetBufferResource,
|
||||
|
||||
+190
-141
@@ -58,8 +58,8 @@ struct Fixture {
|
||||
auto *result = storage.get();
|
||||
program.block_storage.push_back(std::move(storage));
|
||||
program.blocks.push_back(result);
|
||||
program.block_info.push_back(
|
||||
{.id = static_cast<uint32_t>(program.block_info.size())});
|
||||
program.blocks.back()->id =
|
||||
static_cast<uint32_t>(program.blocks.size() - 1u);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ struct Fixture {
|
||||
}
|
||||
|
||||
void PlanAndTrack() {
|
||||
for (size_t index = 0; index < program.block_info.size(); ++index) {
|
||||
const auto condition = program.block_info[index].condition;
|
||||
for (size_t index = 0; index < program.blocks.size(); ++index) {
|
||||
const auto condition = program.blocks[index]->condition;
|
||||
if (!condition.IsEmpty())
|
||||
Emit(ValueOpcode::Reference, {condition}, 0, program.blocks[index]);
|
||||
}
|
||||
@@ -475,9 +475,11 @@ void TestWaterfallImageTable() {
|
||||
{guard, fixture->Emit(ValueOpcode::IEqual32, {image_words[word], local})});
|
||||
}
|
||||
}
|
||||
fixture->program.block_info[0].condition = guard;
|
||||
fixture->program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch, .true_block = 1u, .false_block = 2u};
|
||||
fixture->program.blocks[0]->condition = guard;
|
||||
fixture->program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = fixture->program.blocks[1u],
|
||||
.false_block = fixture->program.blocks[2u]};
|
||||
const auto sample = [&](Value image, Block *block) {
|
||||
const auto sampler = fixture->Sampler({Value(0u), Value(0u), Value(0u), Value(0u)});
|
||||
MemoryInfo memory;
|
||||
@@ -589,19 +591,20 @@ void TestGuardedDirectImageTable() {
|
||||
if (guard != Guard::Plain && guard != Guard::SccNonZero) {
|
||||
condition = fixture.Emit(ValueOpcode::ConditionRef, {condition}, kind);
|
||||
}
|
||||
fixture.program.block_info[0].condition = condition;
|
||||
fixture.program.block_info[0].terminator = {
|
||||
fixture.program.blocks[0]->condition = condition;
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = guard == Guard::Zero ? 1u : 4u,
|
||||
.false_block = guard == Guard::Zero ? 4u : 1u};
|
||||
.true_block = fixture.program.blocks[guard == Guard::Zero ? 1u : 4u],
|
||||
.false_block = fixture.program.blocks[guard == Guard::Zero ? 4u : 1u]};
|
||||
for (uint32_t block = 1; block < 4; ++block) {
|
||||
fixture.program.block_info[block].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = block + 1u};
|
||||
fixture.program.blocks[block]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[block + 1u]};
|
||||
}
|
||||
fixture.program.block_info[4].terminator = {
|
||||
fixture.program.blocks[4]->terminator = {
|
||||
.kind = guard == Guard::Bypass ? CFG::TerminatorKind::Branch
|
||||
: CFG::TerminatorKind::Return,
|
||||
.true_block = 3u};
|
||||
: CFG::TerminatorKind::Return,
|
||||
.true_block = fixture.program.blocks[3u]};
|
||||
const auto srt = fixture.Address(fixture.UserData(0), fixture.UserData(1));
|
||||
std::array<Value, 2> pointer;
|
||||
for (uint32_t word = 0; word < pointer.size(); ++word) {
|
||||
@@ -767,27 +770,40 @@ void TestBoundedComputeImageLoop() {
|
||||
if (variant == Variant::ExitBypass) exit->AddBranch(body);
|
||||
if (variant == Variant::IncrementBypass || variant == Variant::PreviousBound)
|
||||
exit->AddBranch(latch);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = variant == Variant::EntryBypass ? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = 1u, .false_block = 2u};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = variant == Variant::EntryBypass
|
||||
? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = fixture.program.blocks[2u]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = variant == Variant::TrueEdge ? 2u : 4u,
|
||||
.false_block = variant == Variant::TrueEdge ? 4u : 2u};
|
||||
fixture.program.block_info[2].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 3u};
|
||||
fixture.program.block_info[3].terminator = {
|
||||
.kind = variant == Variant::PreviousBound ? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = 1u, .false_block = 5u};
|
||||
fixture.program.block_info[4].terminator = {
|
||||
.true_block =
|
||||
fixture.program.blocks[variant == Variant::TrueEdge ? 2u : 4u],
|
||||
.false_block =
|
||||
fixture.program.blocks[variant == Variant::TrueEdge ? 4u : 2u]};
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[3u]};
|
||||
fixture.program.blocks[3]->terminator = {
|
||||
.kind = variant == Variant::PreviousBound
|
||||
? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = final_exit};
|
||||
fixture.program.blocks[4]->terminator = {
|
||||
.kind = final_exit != exit || variant == Variant::ExitBypass ||
|
||||
variant == Variant::IncrementBypass
|
||||
? CFG::TerminatorKind::Branch : CFG::TerminatorKind::Return,
|
||||
.true_block = final_exit != exit || variant == Variant::IncrementBypass ? 3u : 2u};
|
||||
? CFG::TerminatorKind::Branch
|
||||
: CFG::TerminatorKind::Return,
|
||||
.true_block =
|
||||
fixture.program.blocks[final_exit != exit ||
|
||||
variant == Variant::IncrementBypass
|
||||
? 3u
|
||||
: 2u]};
|
||||
if (final_exit != exit)
|
||||
fixture.program.block_info[5].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[5]->terminator.kind =
|
||||
CFG::TerminatorKind::Return;
|
||||
}
|
||||
|
||||
auto &phi = header->AppendNewInst(ValueOpcode::Phi, {},
|
||||
@@ -859,14 +875,16 @@ void TestBoundedComputeImageLoop() {
|
||||
block->AddBranch(fixture.program.blocks[yes]);
|
||||
block->AddBranch(fixture.program.blocks[no]);
|
||||
const auto inverse = fixture.Emit(ValueOpcode::LogicalNot, {predicate}, 0, block);
|
||||
fixture.program.block_info[index].condition =
|
||||
fixture.program.blocks[index]->condition =
|
||||
fixture.Emit(ValueOpcode::ConditionRef, {inverse}, kind, block);
|
||||
fixture.program.block_info[index].terminator = {
|
||||
fixture.program.blocks[index]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = yes, .false_block = no};
|
||||
.true_block = fixture.program.blocks[yes],
|
||||
.false_block = fixture.program.blocks[no]};
|
||||
};
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
branch(1u, 4u, 5u, active, CFG::BranchCondition::ExecZero);
|
||||
branch(5u, variant == Variant::GuardedDiamondBypass ? 7u : 4u, 6u,
|
||||
diamond ? execute : mask,
|
||||
@@ -877,13 +895,15 @@ void TestBoundedComputeImageLoop() {
|
||||
fixture.Emit(ValueOpcode::IEqual32, {local, Value(1u)}, 0, guard)}, 0, guard);
|
||||
branch(6u, 3u, 2u, image_guard, CFG::BranchCondition::ExecZero);
|
||||
body->AddBranch(latch);
|
||||
fixture.program.block_info[2].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 3u};
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[3u]};
|
||||
branch(3u, 4u, 7u, next_active, CFG::BranchCondition::ExecZero);
|
||||
increment->AddBranch(header);
|
||||
fixture.program.block_info[7].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.block_info[4].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[7]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
fixture.program.blocks[4]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
} else {
|
||||
const auto active = initial_active;
|
||||
const auto allowed = fixture.Emit(variant == Variant::Disjunction
|
||||
@@ -899,14 +919,15 @@ void TestBoundedComputeImageLoop() {
|
||||
: CFG::BranchCondition::ExecZero, header);
|
||||
if (variant == Variant::Nonzero || variant == Variant::WrongPolarity)
|
||||
condition = fixture.Emit(ValueOpcode::LogicalNot, {condition}, 0, header);
|
||||
fixture.program.block_info[1].condition = condition;
|
||||
fixture.program.blocks[1]->condition = condition;
|
||||
if (variant == Variant::PreviousBound) {
|
||||
previous->AddPhiOperand(entry, Value(false));
|
||||
previous->AddPhiOperand(latch, in_range);
|
||||
const auto continuing = fixture.Emit(ValueOpcode::LogicalOr,
|
||||
{in_range, Value(previous)}, 0, latch);
|
||||
fixture.program.block_info[3].condition = fixture.Emit(ValueOpcode::ConditionRef,
|
||||
{continuing}, CFG::BranchCondition::SccNonZero, latch);
|
||||
fixture.program.blocks[3]->condition =
|
||||
fixture.Emit(ValueOpcode::ConditionRef, {continuing},
|
||||
CFG::BranchCondition::SccNonZero, latch);
|
||||
}
|
||||
}
|
||||
const auto step = fixture.Emit(ValueOpcode::IAdd32,
|
||||
@@ -1067,21 +1088,27 @@ void TestUniformizedMaterialImageKeys() {
|
||||
choose->AddBranch(done);
|
||||
if (first_lane) {
|
||||
sample_entry->AddBranch(first_lane_loop ? sample_header : sample);
|
||||
fixture.program.block_info[sample_entry_id].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = first_lane_loop ? 9u : 7u};
|
||||
fixture.program.blocks[sample_entry_id]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[first_lane_loop ? 9u : 7u]};
|
||||
}
|
||||
if (first_lane_loop) {
|
||||
sample_header->AddBranch(sample);
|
||||
sample->AddBranch(sample_header);
|
||||
fixture.program.block_info[9].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 7u,
|
||||
.merge_block = 8u, .continue_block = 7u, .loop_header = true};
|
||||
fixture.program.blocks[9]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[7u],
|
||||
.merge_block = fixture.program.blocks[8u],
|
||||
.continue_block = fixture.program.blocks[7u],
|
||||
.loop_header = true};
|
||||
}
|
||||
sample->AddBranch(done);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 2u};
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[2u]};
|
||||
const auto enabled = fixture.Emit(
|
||||
ValueOpcode::INotEqual32, {fixture.UserData(5u), Value(0u)}, 0, entry);
|
||||
const auto local = fixture.Emit(ValueOpcode::GetBuiltin,
|
||||
@@ -1097,23 +1124,26 @@ void TestUniformizedMaterialImageKeys() {
|
||||
ValueOpcode::Phi, {}, static_cast<uint64_t>(Type::U32));
|
||||
const auto mask = Value(&mask_phi);
|
||||
const auto active = Value(&active_phi);
|
||||
fixture.program.block_info[2].condition = branch(
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {active}, 0, inactive),
|
||||
variant == Variant::WrongExit ? CFG::BranchCondition::ExecNonZero
|
||||
: CFG::BranchCondition::ExecZero, inactive);
|
||||
fixture.program.block_info[2].terminator = {
|
||||
fixture.program.blocks[2]->condition =
|
||||
branch(fixture.Emit(ValueOpcode::LogicalNot, {active}, 0, inactive),
|
||||
variant == Variant::WrongExit ? CFG::BranchCondition::ExecNonZero
|
||||
: CFG::BranchCondition::ExecZero,
|
||||
inactive);
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 5u, .false_block = 3u};
|
||||
.true_block = fixture.program.blocks[5u],
|
||||
.false_block = fixture.program.blocks[3u]};
|
||||
const auto nonzero = fixture.Emit(
|
||||
ValueOpcode::INotEqual32, {Value(0u), mask}, 0, sentinel);
|
||||
const auto bit_guard = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {active, nonzero}, 0, sentinel);
|
||||
fixture.program.block_info[3].condition = branch(
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {bit_guard}, 0, sentinel),
|
||||
CFG::BranchCondition::ExecZero, sentinel);
|
||||
fixture.program.block_info[3].terminator = {
|
||||
fixture.program.blocks[3]->condition =
|
||||
branch(fixture.Emit(ValueOpcode::LogicalNot, {bit_guard}, 0, sentinel),
|
||||
CFG::BranchCondition::ExecZero, sentinel);
|
||||
fixture.program.blocks[3]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 5u, .false_block = 4u};
|
||||
.true_block = fixture.program.blocks[5u],
|
||||
.false_block = fixture.program.blocks[4u]};
|
||||
const auto first = fixture.Emit(ValueOpcode::FindILsb32, {mask}, 0, bit);
|
||||
const auto position = fixture.Emit(
|
||||
ValueOpcode::BitwiseAnd32, {first, Value(31u)}, 0, bit);
|
||||
@@ -1130,11 +1160,12 @@ void TestUniformizedMaterialImageKeys() {
|
||||
{mask, removed}, 0, bit);
|
||||
const auto continuation = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {bit_guard, active_on_entry}, 0, bit);
|
||||
fixture.program.block_info[4].condition = branch(
|
||||
continuation, CFG::BranchCondition::ExecNonZero, bit);
|
||||
fixture.program.block_info[4].terminator = {
|
||||
fixture.program.blocks[4]->condition =
|
||||
branch(continuation, CFG::BranchCondition::ExecNonZero, bit);
|
||||
fixture.program.blocks[4]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 1u, .false_block = 5u};
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = fixture.program.blocks[5u]};
|
||||
active_phi.AddPhiOperand(entry, active_on_entry);
|
||||
active_phi.AddPhiOperand(bit, continuation);
|
||||
mask_phi.AddPhiOperand(entry, fixture.UserData(4u));
|
||||
@@ -1159,8 +1190,9 @@ void TestUniformizedMaterialImageKeys() {
|
||||
ValueOpcode::SGreaterThan32, {Value(32u), index}, 0, merge);
|
||||
const auto material_guard = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {active_on_entry, below}, 0, merge);
|
||||
fixture.program.block_info[5].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 6u};
|
||||
fixture.program.blocks[5]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[6u]};
|
||||
const auto scaled = fixture.Emit(
|
||||
ValueOpcode::ShiftLeftLogical32, {index, Value(4u)}, 0, choose);
|
||||
const auto selected_scale = fixture.Emit(
|
||||
@@ -1202,12 +1234,13 @@ void TestUniformizedMaterialImageKeys() {
|
||||
sample_active_phi->AddPhiOperand(sample_entry, initial);
|
||||
sample_active = Value(sample_active_phi);
|
||||
}
|
||||
fixture.program.block_info[6].condition = branch(
|
||||
variant == Variant::EmptyFirstEntry ? enabled : initial,
|
||||
CFG::BranchCondition::ExecNonZero, choose);
|
||||
fixture.program.block_info[6].terminator = {
|
||||
fixture.program.blocks[6]->condition =
|
||||
branch(variant == Variant::EmptyFirstEntry ? enabled : initial,
|
||||
CFG::BranchCondition::ExecNonZero, choose);
|
||||
fixture.program.blocks[6]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = sample_entry_id, .false_block = 8u};
|
||||
.true_block = fixture.program.blocks[sample_entry_id],
|
||||
.false_block = fixture.program.blocks[8u]};
|
||||
}
|
||||
auto *key_block = first_lane ? sample : choose;
|
||||
const auto key = first_lane
|
||||
@@ -1219,12 +1252,13 @@ void TestUniformizedMaterialImageKeys() {
|
||||
const auto sample_guard = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {sample_active, compared}, 0, key_block);
|
||||
if (!first_lane) {
|
||||
fixture.program.block_info[6].condition = branch(
|
||||
fixture.program.blocks[6]->condition = branch(
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {sample_guard}, 0, choose),
|
||||
CFG::BranchCondition::ExecZero, choose);
|
||||
fixture.program.block_info[6].terminator = {
|
||||
fixture.program.blocks[6]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 8u, .false_block = 7u};
|
||||
.true_block = fixture.program.blocks[8u],
|
||||
.false_block = fixture.program.blocks[7u]};
|
||||
}
|
||||
const auto table_offset = fixture.Emit(
|
||||
ValueOpcode::IAdd32,
|
||||
@@ -1272,17 +1306,19 @@ void TestUniformizedMaterialImageKeys() {
|
||||
if (variant == Variant::WideningFirstBackedge)
|
||||
remaining = fixture.Emit(ValueOpcode::LogicalOr, {remaining, enabled}, 0, sample);
|
||||
sample_active_phi->AddPhiOperand(sample, remaining);
|
||||
fixture.program.block_info[7].condition = branch(
|
||||
fixture.program.blocks[7]->condition = branch(
|
||||
variant == Variant::WrongFirstBackedge ? sample_guard : remaining,
|
||||
CFG::BranchCondition::ExecNonZero, sample);
|
||||
fixture.program.block_info[7].terminator = {
|
||||
fixture.program.blocks[7]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 9u, .false_block = 8u};
|
||||
.true_block = fixture.program.blocks[9u],
|
||||
.false_block = fixture.program.blocks[8u]};
|
||||
} else {
|
||||
fixture.program.block_info[7].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 8u};
|
||||
fixture.program.blocks[7]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[8u]};
|
||||
}
|
||||
fixture.program.block_info[8].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[8]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
const auto output = fixture.Emit(
|
||||
ValueOpcode::GetBufferResource,
|
||||
{fixture.UserData(8u), fixture.UserData(9u),
|
||||
@@ -1556,10 +1592,10 @@ void TestComputeBufferFill() {
|
||||
};
|
||||
const auto Run = [](Options options) {
|
||||
Fixture fixture;
|
||||
fixture.program.block_info[0].terminator.kind =
|
||||
fixture.program.blocks[0]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
if (options.branch) {
|
||||
fixture.program.block_info[0].terminator.kind = Libs::Graphics::
|
||||
fixture.program.blocks[0]->terminator.kind = Libs::Graphics::
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
}
|
||||
const auto buffer =
|
||||
@@ -2369,16 +2405,20 @@ ResourcePlan ConditionalSamplerPlan(bool diamond, bool reverse, bool reverse_phi
|
||||
alternate->AddBranch(merge);
|
||||
if (diamond) {
|
||||
initial->AddBranch(merge);
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = merge_id};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[merge_id]};
|
||||
}
|
||||
fixture.program.block_info[0].terminator = {
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = reverse ? alternate_id : initial_target,
|
||||
.false_block = reverse ? initial_target : alternate_id};
|
||||
fixture.program.block_info[alternate_id].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = merge_id};
|
||||
fixture.program.block_info[merge_id].terminator.kind =
|
||||
.true_block =
|
||||
fixture.program.blocks[reverse ? alternate_id : initial_target],
|
||||
.false_block =
|
||||
fixture.program.blocks[reverse ? initial_target : alternate_id]};
|
||||
fixture.program.blocks[alternate_id]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[merge_id]};
|
||||
fixture.program.blocks[merge_id]->terminator.kind =
|
||||
CFG::TerminatorKind::Return;
|
||||
const auto control =
|
||||
fixture.Buffer({Value(0x2000u), Value(0u), Value(200u), Value(0u)});
|
||||
@@ -2389,7 +2429,7 @@ ResourcePlan ConditionalSamplerPlan(bool diamond, bool reverse, bool reverse_phi
|
||||
if (nonuniform) {
|
||||
flag = fixture.Emit(ValueOpcode::LaneId);
|
||||
}
|
||||
fixture.program.block_info[0].condition =
|
||||
fixture.program.blocks[0]->condition =
|
||||
fixture.Emit(ValueOpcode::SGreaterThanEqual32, {flag, Value(0u)});
|
||||
if (writable) {
|
||||
MemoryInfo memory;
|
||||
@@ -2590,22 +2630,21 @@ void TestFiniteImageBitScanSentinel() {
|
||||
{Value(uint32_t(StageInputKind::LocalInvocationIndex)), Value(0u)});
|
||||
const auto condition = fixture.Emit(nonzero ? ValueOpcode::INotEqual32 : ValueOpcode::IEqual32,
|
||||
{mask, Value(0u)});
|
||||
auto &guard = fixture.program.block_info[0];
|
||||
auto &guard = *fixture.program.blocks[0];
|
||||
guard.condition = condition;
|
||||
guard.terminator.kind = CFG::TerminatorKind::ConditionalBranch;
|
||||
guard.terminator.true_block = 1;
|
||||
guard.terminator.false_block = 4;
|
||||
guard.terminator.true_block = dispatch;
|
||||
guard.terminator.false_block = exit;
|
||||
fixture.block = dispatch;
|
||||
const auto first = fixture.Emit(ValueOpcode::FindILsb32, {mask});
|
||||
const auto minimum = fixture.Emit(ValueOpcode::UMin32, {first, Value(32u)});
|
||||
const auto selector = fixture.Emit(ValueOpcode::ShiftLeftLogical32, {minimum, Value(2u)});
|
||||
fixture.Emit(ValueOpcode::ReferenceU32, {selector});
|
||||
auto &table = fixture.program.block_info[1];
|
||||
auto &table = *fixture.program.blocks[1];
|
||||
table.indirect_target = selector;
|
||||
table.terminator.kind = CFG::TerminatorKind::IndirectBranch;
|
||||
table.terminator.indirect_selector_code = 0;
|
||||
table.terminator.indirect_selector_values = {0u, 128u};
|
||||
table.terminator.indirect_selector_targets = {2u, 3u};
|
||||
table.terminator.indexed = true;
|
||||
table.terminator.cases = {{0u, load}, {128u, merge}};
|
||||
std::array<Value, 8> words;
|
||||
for (uint32_t word = 0; word < words.size(); ++word) {
|
||||
auto &phi = merge->AppendNewInst(ValueOpcode::Phi, {}, uint64_t(Type::U32));
|
||||
@@ -2743,21 +2782,25 @@ void TestBoundedRelativeRegisterWrites() {
|
||||
header->AddBranch(body);
|
||||
header->AddBranch(exit);
|
||||
body->AddBranch(header);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = variant == Variant::EntryBypass ? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = 1u, .false_block = 2u};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = variant == Variant::EntryBypass
|
||||
? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = fixture.program.blocks[2u]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 2u, .false_block = 3u};
|
||||
fixture.program.block_info[2].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.block_info[3].terminator.kind = CFG::TerminatorKind::Return;
|
||||
.true_block = fixture.program.blocks[2u],
|
||||
.false_block = fixture.program.blocks[3u]};
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
fixture.program.blocks[3]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
|
||||
const auto lane = fixture.Emit(ValueOpcode::GetBuiltin,
|
||||
{Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)), Value(0u)});
|
||||
const auto enabled = fixture.Emit(ValueOpcode::ULessThan32, {lane, Value(32u)});
|
||||
fixture.program.block_info[0].condition = enabled;
|
||||
fixture.program.blocks[0]->condition = enabled;
|
||||
const auto chunk = fixture.Emit(ValueOpcode::SelectU32,
|
||||
{enabled, Value(64u), Value(512u)});
|
||||
const auto initial_bound = fixture.Emit(ValueOpcode::ShiftRightLogical32,
|
||||
@@ -2769,8 +2812,9 @@ void TestBoundedRelativeRegisterWrites() {
|
||||
auto &records = header->AppendNewInst(ValueOpcode::Phi, {}, uint64_t(Type::U32));
|
||||
const auto in_range = fixture.Emit(ValueOpcode::ULessThan32,
|
||||
{Value(&counter), Value(&bound)}, 0, header);
|
||||
fixture.program.block_info[1].condition = fixture.Emit(
|
||||
ValueOpcode::ConditionRef, {in_range}, CFG::BranchCondition::VccNonZero, header);
|
||||
fixture.program.blocks[1]->condition =
|
||||
fixture.Emit(ValueOpcode::ConditionRef, {in_range},
|
||||
CFG::BranchCondition::VccNonZero, header);
|
||||
const auto m0 = fixture.Emit(ValueOpcode::BitwiseAnd32,
|
||||
{fixture.Emit(ValueOpcode::ShiftLeftLogical32,
|
||||
{Value(&counter), Value(1u)}, 0, body), Value(255u)}, 0, body);
|
||||
@@ -2953,26 +2997,27 @@ ResourcePlan ConditionalBufferPlan(ConditionalBufferUse use) {
|
||||
auto *done = fixture.AddBlock();
|
||||
auto *condition_block = entry;
|
||||
uint32_t condition_index = 0;
|
||||
fixture.program.block_info[0].id = 11;
|
||||
fixture.program.block_info[1].id = 27;
|
||||
fixture.program.block_info[2].id = 42;
|
||||
fixture.program.blocks[0]->id = 11;
|
||||
fixture.program.blocks[1]->id = 27;
|
||||
fixture.program.blocks[2]->id = 42;
|
||||
if (use == ConditionalBufferUse::Loop) {
|
||||
condition_block = fixture.AddBlock();
|
||||
condition_index = 3;
|
||||
fixture.program.block_info[3].id = 55;
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 55};
|
||||
fixture.program.blocks[3]->id = 55;
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = condition_block};
|
||||
entry->AddBranch(condition_block);
|
||||
}
|
||||
condition_block->AddBranch(optional);
|
||||
condition_block->AddBranch(done);
|
||||
optional->AddBranch(use == ConditionalBufferUse::Loop ? condition_block : done);
|
||||
fixture.program.block_info[condition_index].terminator = {
|
||||
fixture.program.blocks[condition_index]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 27, .false_block = 42};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.true_block = optional,
|
||||
.false_block = done};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = use == ConditionalBufferUse::Loop ? 55u : 42u};
|
||||
.true_block = use == ConditionalBufferUse::Loop ? condition_block : done};
|
||||
|
||||
const auto control = fixture.Buffer(
|
||||
{fixture.UserData(0), fixture.UserData(1), fixture.UserData(2),
|
||||
@@ -2988,8 +3033,8 @@ ResourcePlan ConditionalBufferPlan(ConditionalBufferUse use) {
|
||||
phi.AddPhiOperand(optional, Value(1u));
|
||||
flag = Value(&phi);
|
||||
}
|
||||
fixture.program.block_info[condition_index].condition =
|
||||
fixture.Emit(ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, condition_block);
|
||||
fixture.program.blocks[condition_index]->condition = fixture.Emit(
|
||||
ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, condition_block);
|
||||
|
||||
const auto payload = fixture.Buffer(
|
||||
{fixture.UserData(4), fixture.UserData(5), fixture.UserData(6),
|
||||
@@ -3067,11 +3112,14 @@ void TestGuardedScalarDescriptorReads() {
|
||||
entry->AddBranch(optional);
|
||||
entry->AddBranch(done);
|
||||
optional->AddBranch(done);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch, .true_block = 1, .false_block = 2};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 2};
|
||||
fixture.program.block_info[2].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = fixture.program.blocks[1],
|
||||
.false_block = fixture.program.blocks[2]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[2]};
|
||||
fixture.program.blocks[2]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
const auto control = fixture.Buffer({fixture.UserData(0), fixture.UserData(1),
|
||||
fixture.UserData(2), fixture.UserData(3)});
|
||||
MemoryInfo scalar;
|
||||
@@ -3083,7 +3131,7 @@ void TestGuardedScalarDescriptorReads() {
|
||||
{Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)), Value(0u)});
|
||||
const auto varying = fixture.Emit(ValueOpcode::INotEqual32, {lane, Value(0u)});
|
||||
const auto enabled = fixture.Emit(ValueOpcode::INotEqual32, {flag, Value(0u)});
|
||||
fixture.program.block_info[0].condition =
|
||||
fixture.program.blocks[0]->condition =
|
||||
fixture.Emit(ValueOpcode::LogicalAnd, {varying, enabled});
|
||||
const auto root = fixture.Address(fixture.UserData(4), Value(0u));
|
||||
const auto Load = [&](Block *block) {
|
||||
@@ -3192,15 +3240,16 @@ void TestConditionalIndirectImageMaterialization() {
|
||||
body->AddBranch(done);
|
||||
const auto flag = fixture->Emit(ValueOpcode::GetUserData,
|
||||
{Value(static_cast<ScalarReg>(8))}, 0, entry);
|
||||
fixture->program.block_info[1].condition = fixture->Emit(
|
||||
ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, entry);
|
||||
fixture->program.block_info[1].terminator = {
|
||||
fixture->program.blocks[1]->condition =
|
||||
fixture->Emit(ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, entry);
|
||||
fixture->program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 0, .false_block = 2};
|
||||
fixture->program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 2};
|
||||
.true_block = fixture->program.blocks[0],
|
||||
.false_block = fixture->program.blocks[2]};
|
||||
fixture->program.blocks[0]->terminator = {.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block =
|
||||
fixture->program.blocks[2]};
|
||||
std::swap(fixture->program.blocks[0], fixture->program.blocks[1]);
|
||||
std::swap(fixture->program.block_info[0], fixture->program.block_info[1]);
|
||||
fixture->PlanAndTrack();
|
||||
auto plan = ExtractResourcePlan(fixture->program);
|
||||
std::array<uint32_t, 9> user_data{
|
||||
|
||||
@@ -46,7 +46,7 @@ struct Fixture {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = index});
|
||||
program.blocks.back()->id = index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,14 +624,14 @@ void TestControlFlowValueSurvivesReadLaneFolding() {
|
||||
entry->AddBranch(taken);
|
||||
entry->AddBranch(other);
|
||||
|
||||
auto &entry_info = fixture.program.block_info[0];
|
||||
auto &entry_info = *fixture.program.blocks[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.block_info[1].terminator.kind =
|
||||
entry_info.terminator.true_block = taken;
|
||||
entry_info.terminator.false_block = other;
|
||||
fixture.program.blocks[1]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
fixture.program.block_info[2].terminator.kind =
|
||||
fixture.program.blocks[2]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
|
||||
const auto undef = fixture.Emit(ValueOpcode::UndefU32);
|
||||
|
||||
@@ -34523,7 +34523,6 @@ void CheckIndirectBufferStore(VulkanHarness &vulkan) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = 0});
|
||||
|
||||
auto &lane = block->AppendNewInst(ValueOpcode::LaneId);
|
||||
auto &selector = block->AppendNewInst(ValueOpcode::BitwiseAnd32,
|
||||
@@ -34629,7 +34628,6 @@ void CheckIndirectImageKeySwitch(VulkanHarness &vulkan) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = 0});
|
||||
|
||||
auto &key = block->AppendNewInst(ValueOpcode::LaneId);
|
||||
auto &image =
|
||||
|
||||
+97
-110
@@ -1929,13 +1929,14 @@ void TestSopkCompareImmediateExtension() {
|
||||
};
|
||||
auto translated =
|
||||
TranslateProgram(shader, MakeCompileOptions(ShaderType::Vertex));
|
||||
const auto branch = std::ranges::find_if(
|
||||
translated.program.block_info, [](const auto &block) {
|
||||
return block.terminator.kind == CFG::TerminatorKind::ConditionalBranch;
|
||||
const auto branch =
|
||||
std::ranges::find_if(translated.program.blocks, [](const auto *block) {
|
||||
return block->terminator.kind ==
|
||||
CFG::TerminatorKind::ConditionalBranch;
|
||||
});
|
||||
Check(branch != translated.program.block_info.end(),
|
||||
Check(branch != translated.program.blocks.end(),
|
||||
"captured LUT parameter export branch was lost");
|
||||
const auto condition = branch->condition.Resolve();
|
||||
const auto condition = (*branch)->condition.Resolve();
|
||||
Check(condition.IsImmediate() && condition.U1() == (counts != 6u),
|
||||
"captured LUT unsigned compare suppressed a live parameter export");
|
||||
}
|
||||
@@ -11083,14 +11084,12 @@ void TestNewShaderRecompilerSetpcJumpTable() {
|
||||
Check((result.ir_dump.find("mode=dispatcher") != std::string::npos),
|
||||
"S_SETPC_B64 jump table did not select dispatcher fallback");
|
||||
const auto jump = std::find_if(
|
||||
result.program.block_info.begin(),
|
||||
result.program.block_info.end(), [](const auto &block) {
|
||||
return !block.terminator.indirect_targets.empty();
|
||||
});
|
||||
Check(jump != result.program.block_info.end() &&
|
||||
jump->terminator.indirect_targets.size() == 2,
|
||||
result.program.blocks.begin(), result.program.blocks.end(),
|
||||
[](const auto *block) { return !block->terminator.cases.empty(); });
|
||||
Check(jump != result.program.blocks.end() &&
|
||||
(*jump)->ImmSuccessors().size() == 2,
|
||||
"S_SETPC_B64 jump table did not retain both targets");
|
||||
Check(jump->terminator.indirect_selector_values.size() == 2,
|
||||
Check((*jump)->terminator.cases.size() == 2,
|
||||
"S_SETPC_B64 jump table did not retain selector mapping");
|
||||
Check(
|
||||
(result.ir_dump.find("SLoadDword") == std::string::npos),
|
||||
@@ -11187,31 +11186,21 @@ void TestNewShaderRecompilerSetpcDwordJumpTable() {
|
||||
Check((result.ir_dump.find("mode=dispatcher") != std::string::npos),
|
||||
"subtractive S_SETPC_B64 table did not select dispatcher fallback");
|
||||
const auto jump = std::find_if(
|
||||
result.program.block_info.begin(),
|
||||
result.program.block_info.end(), [](const auto &block) {
|
||||
return !block.terminator.indirect_targets.empty();
|
||||
});
|
||||
const auto block_pc = [&](uint32_t id) {
|
||||
const auto block =
|
||||
std::find_if(result.program.block_info.begin(),
|
||||
result.program.block_info.end(),
|
||||
[=](const auto &info) { return info.id == id; });
|
||||
return block != result.program.block_info.end() ? block->start_pc
|
||||
: UINT32_MAX;
|
||||
};
|
||||
Check(jump != result.program.block_info.end() &&
|
||||
jump->terminator.indirect_targets.size() == 2 &&
|
||||
jump->terminator.indirect_target_pcs ==
|
||||
std::vector<uint32_t>({0x38u, 0x40u}) &&
|
||||
jump->terminator.indirect_selector_values ==
|
||||
std::vector<uint32_t>({0u, 4u, 8u}) &&
|
||||
jump->terminator.indirect_selector_targets.size() == 3 &&
|
||||
block_pc(jump->terminator.indirect_selector_targets[0]) == 0x38u &&
|
||||
block_pc(jump->terminator.indirect_selector_targets[1]) == 0x40u &&
|
||||
block_pc(jump->terminator.indirect_selector_targets[2]) == 0x38u &&
|
||||
result.program.blocks.begin(), result.program.blocks.end(),
|
||||
[](const auto *block) { return !block->terminator.cases.empty(); });
|
||||
Check(jump != result.program.blocks.end() &&
|
||||
(*jump)->ImmSuccessors().size() == 2 &&
|
||||
(*jump)->terminator.indexed &&
|
||||
(*jump)->terminator.cases.size() == 3 &&
|
||||
(*jump)->terminator.cases[0].value == 0u &&
|
||||
(*jump)->terminator.cases[0].target->start_pc == 0x38u &&
|
||||
(*jump)->terminator.cases[1].value == 4u &&
|
||||
(*jump)->terminator.cases[1].target->start_pc == 0x40u &&
|
||||
(*jump)->terminator.cases[2].value == 8u &&
|
||||
(*jump)->terminator.cases[2].target->start_pc == 0x38u &&
|
||||
std::ranges::none_of(
|
||||
result.program.block_info,
|
||||
[](const auto &info) { return info.start_pc == 0x04u; }),
|
||||
result.program.blocks,
|
||||
[](const auto *block) { return block->start_pc == 0x04u; }),
|
||||
"subtractive S_SETPC_B64 table targets or selector mapping changed");
|
||||
Check((result.ir_dump.find("SLoadDword") == std::string::npos),
|
||||
"subtractive S_SETPC_B64 table load reached normal IR");
|
||||
@@ -11802,7 +11791,6 @@ void TestFinalSsaRejectsRegisterStatePseudos() {
|
||||
Program program;
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.emplace_back();
|
||||
IREmitter ir(program.blocks.front());
|
||||
if (setter) {
|
||||
ir.SetScalarReg(ScalarReg{0}, U32(Value(1u)));
|
||||
@@ -11842,7 +11830,7 @@ void TestValuePhiValidation() {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
return block;
|
||||
};
|
||||
|
||||
@@ -11850,17 +11838,17 @@ void TestValuePhiValidation() {
|
||||
auto *left = add_block(1);
|
||||
auto *right = add_block(2);
|
||||
auto *join = add_block(3);
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[0].terminator.false_block = 2;
|
||||
program.block_info[0].condition = Value(true);
|
||||
program.block_info[1].terminator.kind =
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[0]->terminator.false_block = program.blocks[2];
|
||||
program.blocks[0]->condition = Value(true);
|
||||
program.blocks[1]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[1].terminator.true_block = 3;
|
||||
program.block_info[2].terminator.kind =
|
||||
program.blocks[1]->terminator.true_block = program.blocks[3];
|
||||
program.blocks[2]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[2].terminator.true_block = 3;
|
||||
program.blocks[2]->terminator.true_block = program.blocks[3];
|
||||
entry->AddBranch(left);
|
||||
entry->AddBranch(right);
|
||||
left->AddBranch(join);
|
||||
@@ -11910,12 +11898,12 @@ void TestValuePhiValidation() {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = duplicate_id ? 0u : id});
|
||||
program.blocks.back()->id = duplicate_id ? 0u : id;
|
||||
}
|
||||
if (!duplicate_id) {
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
}
|
||||
expect_invalid(program,
|
||||
"malformed Value CFG did not terminate IR validation");
|
||||
@@ -11928,14 +11916,14 @@ void TestValuePhiValidation() {
|
||||
for (uint32_t id = 0; id < 2; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[1].terminator.kind =
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[1]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[1].terminator.true_block = 0;
|
||||
program.blocks[1]->terminator.true_block = program.blocks[0];
|
||||
program.blocks[0]->AddBranch(program.blocks[1]);
|
||||
program.blocks[1]->AddBranch(program.blocks[0]);
|
||||
expect_invalid(program,
|
||||
@@ -11946,17 +11934,15 @@ void TestValuePhiValidation() {
|
||||
for (uint32_t id = 0; id < 3; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
auto &indirect = program.block_info[1];
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
auto &indirect = *program.blocks[1];
|
||||
indirect.terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::IndirectBranch;
|
||||
indirect.terminator.indirect_targets = {1};
|
||||
indirect.terminator.indirect_selector_values = {0};
|
||||
indirect.terminator.indirect_selector_targets = {2};
|
||||
indirect.terminator.cases = {{0, program.blocks[2]}};
|
||||
indirect.indirect_target = Value(0u);
|
||||
program.blocks[0]->AddBranch(program.blocks[1]);
|
||||
program.blocks[1]->AddBranch(program.blocks[1]);
|
||||
@@ -11968,7 +11954,7 @@ void TestValuePhiValidation() {
|
||||
Program program;
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = UINT32_MAX});
|
||||
program.blocks.back()->id = UINT32_MAX;
|
||||
expect_invalid(program,
|
||||
"reserved exit block id did not terminate IR validation");
|
||||
}
|
||||
@@ -11977,27 +11963,29 @@ void TestValuePhiValidation() {
|
||||
for (uint32_t id = 0; id < 2; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
auto &indirect = program.block_info[1];
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
auto &indirect = *program.blocks[1];
|
||||
indirect.terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::IndirectBranch;
|
||||
indirect.terminator.indirect_targets = {1, 1};
|
||||
indirect.terminator.cases = {{0, program.blocks[1]},
|
||||
{0, program.blocks[1]}};
|
||||
indirect.indirect_target = Value(0u);
|
||||
program.blocks[0]->AddBranch(program.blocks[1]);
|
||||
program.blocks[1]->AddBranch(program.blocks[1]);
|
||||
expect_invalid(program,
|
||||
"duplicate indirect targets did not terminate IR validation");
|
||||
expect_invalid(
|
||||
program,
|
||||
"duplicate indirect selector values did not terminate IR validation");
|
||||
}
|
||||
{
|
||||
Program program;
|
||||
for (uint32_t id = 0; id < 2; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
expect_invalid(program,
|
||||
"unreachable block did not terminate IR validation");
|
||||
@@ -12007,7 +11995,6 @@ void TestValuePhiValidation() {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = 0});
|
||||
auto &use =
|
||||
block->AppendNewInst(ValueOpcode::IAdd32, {Value(1u), Value(2u)});
|
||||
auto &definition =
|
||||
@@ -12021,17 +12008,17 @@ void TestValuePhiValidation() {
|
||||
for (uint32_t id = 0; id < 4; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[0].terminator.false_block = 2;
|
||||
program.block_info[0].condition = Value(true);
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[0]->terminator.false_block = program.blocks[2];
|
||||
program.blocks[0]->condition = Value(true);
|
||||
for (uint32_t id : {1u, 2u}) {
|
||||
program.block_info[id].terminator.kind =
|
||||
program.blocks[id]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[id].terminator.true_block = 3;
|
||||
program.blocks[id]->terminator.true_block = program.blocks[3];
|
||||
}
|
||||
program.blocks[0]->AddBranch(program.blocks[1]);
|
||||
program.blocks[0]->AddBranch(program.blocks[2]);
|
||||
@@ -12049,17 +12036,17 @@ void TestValuePhiValidation() {
|
||||
for (uint32_t id = 0; id < 4; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[0].terminator.false_block = 2;
|
||||
program.block_info[0].condition = Value(true);
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[0]->terminator.false_block = program.blocks[2];
|
||||
program.blocks[0]->condition = Value(true);
|
||||
for (uint32_t id : {1u, 2u}) {
|
||||
program.block_info[id].terminator.kind =
|
||||
program.blocks[id]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[id].terminator.true_block = 3;
|
||||
program.blocks[id]->terminator.true_block = program.blocks[3];
|
||||
}
|
||||
program.blocks[0]->AddBranch(program.blocks[1]);
|
||||
program.blocks[0]->AddBranch(program.blocks[2]);
|
||||
@@ -12080,23 +12067,23 @@ void TestValuePhiValidation() {
|
||||
for (uint32_t id = 0; id < 5; id++) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
program.block_info[0].terminator.kind =
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[0].terminator.false_block = 2;
|
||||
program.block_info[0].condition = Value(true);
|
||||
program.block_info[1].terminator.kind =
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[0]->terminator.false_block = program.blocks[2];
|
||||
program.blocks[0]->condition = Value(true);
|
||||
program.blocks[1]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[1].terminator.true_block = 3;
|
||||
program.block_info[2].terminator.kind =
|
||||
program.blocks[1]->terminator.true_block = program.blocks[3];
|
||||
program.blocks[2]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[2].terminator.true_block = 3;
|
||||
program.block_info[2].terminator.false_block = 4;
|
||||
program.block_info[3].terminator.kind =
|
||||
program.blocks[2]->terminator.true_block = program.blocks[3];
|
||||
program.blocks[2]->terminator.false_block = program.blocks[4];
|
||||
program.blocks[3]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[3].terminator.true_block = 4;
|
||||
program.blocks[3]->terminator.true_block = program.blocks[4];
|
||||
program.blocks[0]->AddBranch(program.blocks[1]);
|
||||
program.blocks[0]->AddBranch(program.blocks[2]);
|
||||
program.blocks[1]->AddBranch(program.blocks[3]);
|
||||
@@ -12105,7 +12092,7 @@ void TestValuePhiValidation() {
|
||||
program.blocks[3]->AddBranch(program.blocks[4]);
|
||||
auto &condition = program.blocks[1]->AppendNewInst(ValueOpcode::IEqual32,
|
||||
{Value(1u), Value(2u)});
|
||||
program.block_info[2].condition = Value(&condition);
|
||||
program.blocks[2]->condition = Value(&condition);
|
||||
expect_invalid(program,
|
||||
"non-dominating branch condition did not terminate IR "
|
||||
"validation");
|
||||
@@ -12122,19 +12109,22 @@ void TestWave32MaskProjection() {
|
||||
for (uint32_t id = 0; id < 3; ++id) {
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.push_back({.id = id});
|
||||
program.blocks.back()->id = id;
|
||||
}
|
||||
auto *entry = program.blocks[0];
|
||||
auto *loop = program.blocks[1];
|
||||
entry->AddBranch(loop);
|
||||
loop->AddBranch(loop);
|
||||
loop->AddBranch(program.blocks[2]);
|
||||
program.block_info[0].terminator.kind = ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.block_info[0].terminator.true_block = 1;
|
||||
program.block_info[1].terminator.kind = ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.block_info[1].terminator.true_block = 1;
|
||||
program.block_info[1].terminator.false_block = 2;
|
||||
program.block_info[2].terminator.kind = ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
program.blocks[0]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Branch;
|
||||
program.blocks[0]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[1]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
program.blocks[1]->terminator.true_block = program.blocks[1];
|
||||
program.blocks[1]->terminator.false_block = program.blocks[2];
|
||||
program.blocks[2]->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
IREmitter e(entry);
|
||||
const auto zero = U32(Value(0u));
|
||||
const auto raw = e.GetUserData(static_cast<ScalarReg>(0));
|
||||
@@ -12188,7 +12178,7 @@ void TestWave32MaskProjection() {
|
||||
mask.AddPhiOperand(loop, remaining);
|
||||
predicate.AddPhiOperand(entry, initial_predicate);
|
||||
predicate.AddPhiOperand(loop, remaining_predicate);
|
||||
program.block_info[1].condition = remaining_predicate;
|
||||
program.blocks[1]->condition = remaining_predicate;
|
||||
|
||||
ConstantPropagationPass(program.blocks, wave_size);
|
||||
if (wave_size == 32u) {
|
||||
@@ -12237,7 +12227,6 @@ void TestU64ShiftConstantPropagation() {
|
||||
Program shifts;
|
||||
shifts.block_storage.push_back(std::make_unique<Block>());
|
||||
shifts.blocks.push_back(shifts.block_storage.back().get());
|
||||
shifts.block_info.emplace_back();
|
||||
IREmitter shift_ir(shifts.blocks.front());
|
||||
struct ShiftCase {
|
||||
Value value;
|
||||
@@ -12309,9 +12298,7 @@ void TestNativeWideValueValidation() {
|
||||
Program program;
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
program.blocks.push_back(program.block_storage.back().get());
|
||||
program.block_info.emplace_back();
|
||||
program.block_info.front().id = 0;
|
||||
program.block_info.front().terminator.kind =
|
||||
program.blocks.front()->terminator.kind =
|
||||
ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
return program;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user