shader: Fix control flow

This commit is contained in:
ReinUsesLisp 2021-02-24 05:21:30 -03:00 committed by ameerj
parent 9d6a98d950
commit e87a502da2
8 changed files with 39 additions and 20 deletions

View file

@ -134,18 +134,27 @@ void IREmitter::SetOFlag(const U1& value) {
Inst(Opcode::SetOFlag, value); Inst(Opcode::SetOFlag, value);
} }
U1 IREmitter::Condition(IR::Condition cond) { static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
if (cond == IR::Condition{true}) { switch (flow_test) {
return Imm1(true); case FlowTest::T:
} else if (cond == IR::Condition{false}) { return ir.Imm1(true);
return Imm1(false); case FlowTest::F:
return ir.Imm1(false);
case FlowTest::EQ:
// TODO: Test this
return ir.GetZFlag();
case FlowTest::NE:
// TODO: Test this
return ir.LogicalNot(ir.GetZFlag());
default:
throw NotImplementedException("Flow test {}", flow_test);
} }
}
U1 IREmitter::Condition(IR::Condition cond) {
const FlowTest flow_test{cond.FlowTest()}; const FlowTest flow_test{cond.FlowTest()};
const auto [pred, is_negated]{cond.Pred()}; const auto [pred, is_negated]{cond.Pred()};
if (flow_test == FlowTest::T) { return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test));
return GetPred(pred, is_negated);
}
throw NotImplementedException("Condition {}", cond);
} }
F32 IREmitter::GetAttribute(IR::Attribute attribute) { F32 IREmitter::GetAttribute(IR::Attribute attribute) {

View file

@ -4,8 +4,8 @@
// opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, ... // opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, ...
OPCODE(Phi, Opaque, ) OPCODE(Phi, Opaque, )
OPCODE(Void, Void, )
OPCODE(Identity, Opaque, Opaque, ) OPCODE(Identity, Opaque, Opaque, )
OPCODE(Void, Void, )
// Control flow // Control flow
OPCODE(Branch, Void, Label, ) OPCODE(Branch, Void, Label, )

View file

@ -329,7 +329,6 @@ private:
if (!sibling) { if (!sibling) {
throw LogicError("Not siblings"); throw LogicError("Not siblings");
} }
// goto_stmt and label_stmt are guaranteed to be siblings, eliminate // goto_stmt and label_stmt are guaranteed to be siblings, eliminate
if (std::next(goto_stmt) == label_stmt) { if (std::next(goto_stmt) == label_stmt) {
// Simply eliminate the goto if the label is next to it // Simply eliminate the goto if the label is next to it
@ -351,9 +350,14 @@ private:
const std::unordered_map labels_map{BuildLabels(blocks)}; const std::unordered_map labels_map{BuildLabels(blocks)};
Tree& root{root_stmt.children}; Tree& root{root_stmt.children};
auto insert_point{root.begin()}; auto insert_point{root.begin()};
// Skip all goto variables zero-initialization
std::advance(insert_point, labels_map.size());
for (Block* const block : blocks) { for (Block* const block : blocks) {
++insert_point; // Skip label // Skip label
++insert_point; // Skip set variable ++insert_point;
// Skip set variable
++insert_point;
root.insert(insert_point, *pool.Create(block, &root_stmt)); root.insert(insert_point, *pool.Create(block, &root_stmt));
if (block->IsTerminationBlock()) { if (block->IsTerminationBlock()) {
@ -391,6 +395,7 @@ private:
labels_map.emplace(block, root.insert(root.end(), *label)); labels_map.emplace(block, root.insert(root.end(), *label));
Statement* const false_stmt{pool.Create(Identity{}, Condition{false})}; Statement* const false_stmt{pool.Create(Identity{}, Condition{false})};
root.push_back(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt)); root.push_back(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt));
root.push_front(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt));
++label_id; ++label_id;
} }
return labels_map; return labels_map;
@ -457,10 +462,10 @@ private:
} }
body.erase(goto_stmt); body.erase(goto_stmt);
// Update nested if condition
switch (label_nested_stmt->type) { switch (label_nested_stmt->type) {
case StatementType::If: case StatementType::If:
label_nested_stmt->cond = pool.Create(Or{}, neg_var, label_nested_stmt->cond); // Update nested if condition
label_nested_stmt->cond = pool.Create(Or{}, variable, label_nested_stmt->cond);
break; break;
case StatementType::Loop: case StatementType::Loop:
break; break;

View file

@ -36,6 +36,10 @@ bool Value::IsIdentity() const noexcept {
return type == Type::Opaque && inst->Opcode() == Opcode::Identity; return type == Type::Opaque && inst->Opcode() == Opcode::Identity;
} }
bool Value::IsPhi() const noexcept {
return type == Type::Opaque && inst->Opcode() == Opcode::Phi;
}
bool Value::IsEmpty() const noexcept { bool Value::IsEmpty() const noexcept {
return type == Type::Void; return type == Type::Void;
} }
@ -52,7 +56,7 @@ bool Value::IsLabel() const noexcept {
} }
IR::Type Value::Type() const noexcept { IR::Type Value::Type() const noexcept {
if (IsIdentity()) { if (IsIdentity() || IsPhi()) {
return inst->Arg(0).Type(); return inst->Arg(0).Type();
} }
if (type == Type::Opaque) { if (type == Type::Opaque) {

View file

@ -33,6 +33,7 @@ public:
explicit Value(f64 value) noexcept; explicit Value(f64 value) noexcept;
[[nodiscard]] bool IsIdentity() const noexcept; [[nodiscard]] bool IsIdentity() const noexcept;
[[nodiscard]] bool IsPhi() const noexcept;
[[nodiscard]] bool IsEmpty() const noexcept; [[nodiscard]] bool IsEmpty() const noexcept;
[[nodiscard]] bool IsImmediate() const noexcept; [[nodiscard]] bool IsImmediate() const noexcept;
[[nodiscard]] bool IsLabel() const noexcept; [[nodiscard]] bool IsLabel() const noexcept;

View file

@ -354,7 +354,7 @@ void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc,
// Impersonate the visited block with a virtual block // Impersonate the visited block with a virtual block
*block = std::move(virtual_block); *block = std::move(virtual_block);
// Set the end properties of the conditional instruction // Set the end properties of the conditional instruction
conditional_block->end = pc; conditional_block->end = pc + 1;
conditional_block->end_class = insn_end_class; conditional_block->end_class = insn_end_class;
// Add a label to the instruction after the conditional instruction // Add a label to the instruction after the conditional instruction
Block* const endif_block{AddLabel(conditional_block, block->stack, pc + 1, function_id)}; Block* const endif_block{AddLabel(conditional_block, block->stack, pc + 1, function_id)};

View file

@ -209,7 +209,7 @@ public:
void P2R_cbuf(u64 insn); void P2R_cbuf(u64 insn);
void P2R_imm(u64 insn); void P2R_imm(u64 insn);
void PBK(); void PBK();
void PCNT(u64 insn); void PCNT();
void PEXIT(u64 insn); void PEXIT(u64 insn);
void PIXLD(u64 insn); void PIXLD(u64 insn);
void PLONGJMP(u64 insn); void PLONGJMP(u64 insn);

View file

@ -637,8 +637,8 @@ void TranslatorVisitor::PBK() {
// PBK is a no-op // PBK is a no-op
} }
void TranslatorVisitor::PCNT(u64) { void TranslatorVisitor::PCNT() {
ThrowNotImplemented(Opcode::PCNT); // PCNT is a no-op
} }
void TranslatorVisitor::PEXIT(u64) { void TranslatorVisitor::PEXIT(u64) {