mirror of
https://github.com/yuzu-emu/yuzu-android
synced 2024-12-29 11:11:21 -08:00
shader: Fix control flow
This commit is contained in:
parent
9d6a98d950
commit
e87a502da2
@ -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) {
|
||||||
|
@ -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, )
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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)};
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user