shader: Improve goto removal algorithm complexity
Find sibling node containing a nephew searching from the nephew itself instead of the uncle.
This commit is contained in:
parent
f66851e376
commit
cc0fcd1b8d
|
@ -222,27 +222,6 @@ std::string DumpTree(const Tree& tree, u32 indentation = 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasNode(const Tree& tree, ConstNode stmt) {
|
|
||||||
const auto end{tree.end()};
|
|
||||||
for (auto it = tree.begin(); it != end; ++it) {
|
|
||||||
if (it == stmt || (HasChildren(it->type) && HasNode(it->children, stmt))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node FindStatementWithLabel(Tree& tree, ConstNode goto_stmt) {
|
|
||||||
const ConstNode label_stmt{goto_stmt->label};
|
|
||||||
const ConstNode end{tree.end()};
|
|
||||||
for (auto it = tree.begin(); it != end; ++it) {
|
|
||||||
if (it == label_stmt || (HasChildren(it->type) && HasNode(it->children, label_stmt))) {
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw LogicError("Lift label not in tree");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SanitizeNoBreaks(const Tree& tree) {
|
void SanitizeNoBreaks(const Tree& tree) {
|
||||||
if (std::ranges::find(tree, StatementType::Break, &Statement::type) != tree.end()) {
|
if (std::ranges::find(tree, StatementType::Break, &Statement::type) != tree.end()) {
|
||||||
throw NotImplementedException("Capturing statement with break nodes");
|
throw NotImplementedException("Capturing statement with break nodes");
|
||||||
|
@ -288,22 +267,6 @@ bool IsIndirectlyRelated(Node goto_stmt, Node label_stmt) {
|
||||||
return goto_stmt->up != label_stmt->up && !IsDirectlyRelated(goto_stmt, label_stmt);
|
return goto_stmt->up != label_stmt->up && !IsDirectlyRelated(goto_stmt, label_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchNode(const Tree& tree, ConstNode stmt, size_t& offset) {
|
|
||||||
++offset;
|
|
||||||
|
|
||||||
const auto end = tree.end();
|
|
||||||
for (ConstNode it = tree.begin(); it != end; ++it) {
|
|
||||||
++offset;
|
|
||||||
if (stmt == it) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (HasChildren(it->type) && SearchNode(it->children, stmt, offset)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AreSiblings(Node goto_stmt, Node label_stmt) noexcept {
|
bool AreSiblings(Node goto_stmt, Node label_stmt) noexcept {
|
||||||
Node it{goto_stmt};
|
Node it{goto_stmt};
|
||||||
do {
|
do {
|
||||||
|
@ -321,6 +284,30 @@ bool AreSiblings(Node goto_stmt, Node label_stmt) noexcept {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node SiblingFromNephew(Node uncle, Node nephew) noexcept {
|
||||||
|
Statement* const parent{uncle->up};
|
||||||
|
Statement* it{&*nephew};
|
||||||
|
while (it->up != parent) {
|
||||||
|
it = it->up;
|
||||||
|
}
|
||||||
|
return Tree::s_iterator_to(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AreOrdered(Node left_sibling, Node right_sibling) noexcept {
|
||||||
|
const Node end{right_sibling->up->children.end()};
|
||||||
|
for (auto it = right_sibling; it != end; ++it) {
|
||||||
|
if (it == left_sibling) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NeedsLift(Node goto_stmt, Node label_stmt) noexcept {
|
||||||
|
const Node sibling{SiblingFromNephew(goto_stmt, label_stmt)};
|
||||||
|
return AreOrdered(sibling, goto_stmt);
|
||||||
|
}
|
||||||
|
|
||||||
class GotoPass {
|
class GotoPass {
|
||||||
public:
|
public:
|
||||||
explicit GotoPass(Flow::CFG& cfg, ObjectPool<IR::Inst>& inst_pool_,
|
explicit GotoPass(Flow::CFG& cfg, ObjectPool<IR::Inst>& inst_pool_,
|
||||||
|
@ -358,7 +345,7 @@ private:
|
||||||
--goto_level;
|
--goto_level;
|
||||||
}
|
}
|
||||||
} else { // Level(goto_stmt) < Level(label_stmt)
|
} else { // Level(goto_stmt) < Level(label_stmt)
|
||||||
if (Offset(goto_stmt) > Offset(label_stmt)) {
|
if (NeedsLift(goto_stmt, label_stmt)) {
|
||||||
// Lift goto_stmt to above stmt containing label_stmt using goto-lifting
|
// Lift goto_stmt to above stmt containing label_stmt using goto-lifting
|
||||||
// transformations
|
// transformations
|
||||||
goto_stmt = Lift(goto_stmt);
|
goto_stmt = Lift(goto_stmt);
|
||||||
|
@ -378,7 +365,7 @@ private:
|
||||||
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
|
||||||
goto_stmt->up->children.erase(goto_stmt);
|
goto_stmt->up->children.erase(goto_stmt);
|
||||||
} else if (Offset(goto_stmt) < Offset(label_stmt)) {
|
} else if (AreOrdered(goto_stmt, label_stmt)) {
|
||||||
// Eliminate goto_stmt with a conditional
|
// Eliminate goto_stmt with a conditional
|
||||||
EliminateAsConditional(goto_stmt, label_stmt);
|
EliminateAsConditional(goto_stmt, label_stmt);
|
||||||
} else {
|
} else {
|
||||||
|
@ -523,8 +510,8 @@ private:
|
||||||
[[nodiscard]] Node MoveInward(Node goto_stmt) {
|
[[nodiscard]] Node MoveInward(Node goto_stmt) {
|
||||||
Statement* const parent{goto_stmt->up};
|
Statement* const parent{goto_stmt->up};
|
||||||
Tree& body{parent->children};
|
Tree& body{parent->children};
|
||||||
const Node label_nested_stmt{FindStatementWithLabel(body, goto_stmt)};
|
|
||||||
const Node label{goto_stmt->label};
|
const Node label{goto_stmt->label};
|
||||||
|
const Node label_nested_stmt{SiblingFromNephew(goto_stmt, label)};
|
||||||
const u32 label_id{label->id};
|
const u32 label_id{label->id};
|
||||||
|
|
||||||
Statement* const goto_cond{goto_stmt->cond};
|
Statement* const goto_cond{goto_stmt->cond};
|
||||||
|
@ -562,7 +549,7 @@ private:
|
||||||
Tree& body{parent->children};
|
Tree& body{parent->children};
|
||||||
const Node label{goto_stmt->label};
|
const Node label{goto_stmt->label};
|
||||||
const u32 label_id{label->id};
|
const u32 label_id{label->id};
|
||||||
const Node label_nested_stmt{FindStatementWithLabel(body, goto_stmt)};
|
const Node label_nested_stmt{SiblingFromNephew(goto_stmt, label)};
|
||||||
|
|
||||||
Tree loop_body;
|
Tree loop_body;
|
||||||
loop_body.splice(loop_body.begin(), body, label_nested_stmt, goto_stmt);
|
loop_body.splice(loop_body.begin(), body, label_nested_stmt, goto_stmt);
|
||||||
|
@ -627,14 +614,6 @@ private:
|
||||||
return parent_tree.insert(std::next(loop), *new_goto);
|
return parent_tree.insert(std::next(loop), *new_goto);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Offset(ConstNode stmt) const {
|
|
||||||
size_t offset{0};
|
|
||||||
if (!SearchNode(root_stmt.children, stmt, offset)) {
|
|
||||||
throw LogicError("Node not found in tree");
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectPool<IR::Inst>& inst_pool;
|
ObjectPool<IR::Inst>& inst_pool;
|
||||||
ObjectPool<IR::Block>& block_pool;
|
ObjectPool<IR::Block>& block_pool;
|
||||||
ObjectPool<Statement>& pool;
|
ObjectPool<Statement>& pool;
|
||||||
|
|
Reference in New Issue