-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Opt] [refactor] Move unreachable code elimination to a separate pass (…
…#1315) * [Opt] [refactor] Move unreachable code elimination to a separate pass * improve * minor * [skip ci] minor * Update taichi/transforms/continue_stmt_optimization.cpp Co-authored-by: Yuanming Hu <yuanming-hu@users.noreply.github.com> * add optimizations for if (0) and if (1) Co-authored-by: Yuanming Hu <yuanming-hu@users.noreply.github.com>
- Loading branch information
1 parent
0bac039
commit 384dfbe
Showing
3 changed files
with
135 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include "taichi/ir/ir.h" | ||
#include "taichi/ir/visitors.h" | ||
#include "taichi/ir/transforms.h" | ||
|
||
TLANG_NAMESPACE_BEGIN | ||
|
||
// Unconditionally eliminate ContinueStmt's at **ends** of loops | ||
class UselessContinueEliminator : public IRVisitor { | ||
public: | ||
bool modified; | ||
|
||
UselessContinueEliminator() : modified(false) { | ||
allow_undefined_visitor = true; | ||
} | ||
|
||
void visit(ContinueStmt *stmt) override { | ||
stmt->parent->erase(stmt); | ||
modified = true; | ||
} | ||
|
||
void visit(IfStmt *if_stmt) override { | ||
if (if_stmt->true_statements && if_stmt->true_statements->size()) | ||
if_stmt->true_statements->back()->accept(this); | ||
if (if_stmt->false_statements && if_stmt->false_statements->size()) | ||
if_stmt->false_statements->back()->accept(this); | ||
} | ||
}; | ||
|
||
// Eliminate useless ContinueStmt, the statements after ContinueStmt and | ||
// unreachable if branches | ||
class UnreachableCodeEliminator : public BasicStmtVisitor { | ||
public: | ||
using BasicStmtVisitor::visit; | ||
bool modified; | ||
UselessContinueEliminator useless_continue_eliminator; | ||
|
||
UnreachableCodeEliminator() : modified(false) { | ||
allow_undefined_visitor = true; | ||
} | ||
|
||
void visit(Block *stmt_list) override { | ||
const int block_size = stmt_list->size(); | ||
for (int i = 0; i < block_size - 1; i++) { | ||
if (stmt_list->statements[i]->is<ContinueStmt>()) { | ||
// Eliminate statements after ContinueStmt | ||
for (int j = block_size - 1; j > i; j--) | ||
stmt_list->erase(j); | ||
modified = true; | ||
break; | ||
} | ||
} | ||
for (auto &stmt : stmt_list->statements) | ||
stmt->accept(this); | ||
} | ||
|
||
void visit_loop(Block *body) { | ||
if (body->size()) | ||
body->back()->accept(&useless_continue_eliminator); | ||
body->accept(this); | ||
} | ||
|
||
void visit(RangeForStmt *stmt) override { | ||
visit_loop(stmt->body.get()); | ||
} | ||
|
||
void visit(StructForStmt *stmt) override { | ||
visit_loop(stmt->body.get()); | ||
} | ||
|
||
void visit(WhileStmt *stmt) override { | ||
visit_loop(stmt->body.get()); | ||
} | ||
|
||
void visit(OffloadedStmt *stmt) override { | ||
if (stmt->prologue) | ||
stmt->prologue->accept(this); | ||
if (stmt->task_type == OffloadedStmt::TaskType::range_for || | ||
stmt->task_type == OffloadedStmt::TaskType::struct_for) | ||
visit_loop(stmt->body.get()); | ||
else if (stmt->body) | ||
stmt->body->accept(this); | ||
if (stmt->epilogue) | ||
stmt->epilogue->accept(this); | ||
} | ||
|
||
void visit(IfStmt *if_stmt) override { | ||
if (if_stmt->cond->is<ConstStmt>() && if_stmt->cond->width() == 1) { | ||
if (if_stmt->cond->as<ConstStmt>()->val[0].equal_value(0)) { | ||
// if (0) | ||
if (if_stmt->true_statements) { | ||
if_stmt->true_statements = nullptr; | ||
modified = true; | ||
} | ||
} else { | ||
// if (1) | ||
if (if_stmt->false_statements) { | ||
if_stmt->false_statements = nullptr; | ||
modified = true; | ||
} | ||
} | ||
} | ||
if (if_stmt->true_statements) | ||
if_stmt->true_statements->accept(this); | ||
if (if_stmt->false_statements) | ||
if_stmt->false_statements->accept(this); | ||
} | ||
|
||
static bool run(IRNode *node) { | ||
bool modified = false; | ||
while (true) { | ||
UnreachableCodeEliminator eliminator; | ||
node->accept(&eliminator); | ||
if (eliminator.modified || | ||
eliminator.useless_continue_eliminator.modified) { | ||
modified = true; | ||
} else { | ||
break; | ||
} | ||
} | ||
return modified; | ||
} | ||
}; | ||
|
||
namespace irpass { | ||
bool unreachable_code_elimination(IRNode *root) { | ||
TI_AUTO_PROF; | ||
return UnreachableCodeEliminator::run(root); | ||
} | ||
} // namespace irpass | ||
|
||
TLANG_NAMESPACE_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters