glasm: Rework control flow introducing a syntax list
This commit regresses VertexA shaders, their transformation pass has to be adapted to the new control flow.
This commit is contained in:
parent
7ff5851608
commit
d54d7de40e
33 changed files with 437 additions and 505 deletions
|
@ -353,24 +353,6 @@ IR::Value EvalImmediates(const IR::Inst& inst, Func&& func, std::index_sequence<
|
|||
return IR::Value{func(Arg<typename Traits::template ArgType<I>>(inst.Arg(I))...)};
|
||||
}
|
||||
|
||||
void FoldBranchConditional(IR::Inst& inst) {
|
||||
const IR::U1 cond{inst.Arg(0)};
|
||||
if (cond.IsImmediate()) {
|
||||
// TODO: Convert to Branch
|
||||
return;
|
||||
}
|
||||
const IR::Inst* cond_inst{cond.InstRecursive()};
|
||||
if (cond_inst->GetOpcode() == IR::Opcode::LogicalNot) {
|
||||
const IR::Value true_label{inst.Arg(1)};
|
||||
const IR::Value false_label{inst.Arg(2)};
|
||||
// Remove negation on the conditional (take the parameter out of LogicalNot) and swap
|
||||
// the branches
|
||||
inst.SetArg(0, cond_inst->Arg(0));
|
||||
inst.SetArg(1, false_label);
|
||||
inst.SetArg(2, true_label);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<IR::Value> FoldCompositeExtractImpl(IR::Value inst_value, IR::Opcode insert,
|
||||
IR::Opcode construct, u32 first_index) {
|
||||
IR::Inst* const inst{inst_value.InstRecursive()};
|
||||
|
@ -581,8 +563,6 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
|
|||
return (base & ~(~(~0u << bits) << offset)) | (insert << offset);
|
||||
});
|
||||
return;
|
||||
case IR::Opcode::BranchConditional:
|
||||
return FoldBranchConditional(inst);
|
||||
case IR::Opcode::CompositeExtractF32x2:
|
||||
return FoldCompositeExtract(inst, IR::Opcode::CompositeConstructF32x2,
|
||||
IR::Opcode::CompositeInsertF32x2);
|
||||
|
|
|
@ -13,60 +13,16 @@
|
|||
|
||||
namespace Shader::Optimization {
|
||||
|
||||
void VertexATransformPass(IR::Program& program) {
|
||||
bool replaced_join{};
|
||||
bool eliminated_epilogue{};
|
||||
for (IR::Block* const block : program.post_order_blocks) {
|
||||
for (IR::Inst& inst : block->Instructions()) {
|
||||
switch (inst.GetOpcode()) {
|
||||
case IR::Opcode::Return:
|
||||
inst.ReplaceOpcode(IR::Opcode::Join);
|
||||
replaced_join = true;
|
||||
break;
|
||||
case IR::Opcode::Epilogue:
|
||||
inst.Invalidate();
|
||||
eliminated_epilogue = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (replaced_join && eliminated_epilogue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void VertexATransformPass(IR::Program&) {
|
||||
throw NotImplementedException("VertexA pass");
|
||||
}
|
||||
|
||||
void VertexBTransformPass(IR::Program& program) {
|
||||
for (IR::Block* const block : program.blocks) {
|
||||
for (IR::Inst& inst : block->Instructions()) {
|
||||
if (inst.GetOpcode() == IR::Opcode::Prologue) {
|
||||
return inst.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
void VertexBTransformPass(IR::Program&) {
|
||||
throw NotImplementedException("VertexA pass");
|
||||
}
|
||||
|
||||
void DualVertexJoinPass(IR::Program& program) {
|
||||
const auto& blocks = program.blocks;
|
||||
const s64 sub_size = static_cast<s64>(blocks.size()) - 1;
|
||||
if (sub_size < 1) {
|
||||
throw LogicError("Dual Vertex Join pass failed, expected atleast 2 blocks");
|
||||
}
|
||||
for (s64 index = 0; index < sub_size; ++index) {
|
||||
IR::Block* const current_block{blocks[index]};
|
||||
IR::Block* const next_block{blocks[index + 1]};
|
||||
for (IR::Inst& inst : current_block->Instructions()) {
|
||||
if (inst.GetOpcode() == IR::Opcode::Join) {
|
||||
IR::IREmitter ir{*current_block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
ir.Branch(next_block);
|
||||
inst.Invalidate();
|
||||
// Only 1 join should exist
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw LogicError("Dual Vertex Join pass failed, no join present");
|
||||
void DualVertexJoinPass(IR::Program&) {
|
||||
throw NotImplementedException("VertexA pass");
|
||||
}
|
||||
|
||||
} // namespace Shader::Optimization
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace Shader::Optimization {
|
|||
|
||||
void IdentityRemovalPass(IR::Program& program) {
|
||||
std::vector<IR::Inst*> to_invalidate;
|
||||
|
||||
for (IR::Block* const block : program.blocks) {
|
||||
for (auto inst = block->begin(); inst != block->end();) {
|
||||
const size_t num_args{inst->NumArgs()};
|
||||
|
|
|
@ -202,7 +202,7 @@ public:
|
|||
|
||||
incomplete_phis[block].insert_or_assign(variable, phi);
|
||||
stack.back().result = IR::Value{&*phi};
|
||||
} else if (const std::span imm_preds{block->ImmediatePredecessors()};
|
||||
} else if (const std::span imm_preds = block->ImmPredecessors();
|
||||
imm_preds.size() == 1) {
|
||||
// Optimize the common case of one predecessor: no phi needed
|
||||
stack.back().pc = Status::SetValue;
|
||||
|
@ -257,7 +257,7 @@ public:
|
|||
private:
|
||||
template <typename Type>
|
||||
IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) {
|
||||
for (IR::Block* const imm_pred : block->ImmediatePredecessors()) {
|
||||
for (IR::Block* const imm_pred : block->ImmPredecessors()) {
|
||||
phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred));
|
||||
}
|
||||
return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue