From 4fde66e6094b57201d208b8abd3d7715341cd5db Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 27 Jun 2019 18:57:47 -0400 Subject: shader_ir: Add basic goto elimination --- src/video_core/shader/ast.h | 174 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 152 insertions(+), 22 deletions(-) (limited to 'src/video_core/shader/ast.h') diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h index ca71543fb..22ac8884c 100644 --- a/src/video_core/shader/ast.h +++ b/src/video_core/shader/ast.h @@ -18,32 +18,71 @@ namespace VideoCommon::Shader { class ASTBase; class ASTProgram; -class ASTIf; +class ASTIfThen; +class ASTIfElse; class ASTBlockEncoded; class ASTVarSet; class ASTGoto; class ASTLabel; class ASTDoWhile; class ASTReturn; +class ASTBreak; -using ASTData = std::variant; +using ASTData = std::variant; using ASTNode = std::shared_ptr; +enum class ASTZipperType : u32 { + Program, + IfThen, + IfElse, + Loop, +}; + +class ASTZipper final { +public: + ASTZipper(); + ASTZipper(ASTNode first); + + ASTNode GetFirst() { + return first; + } + + ASTNode GetLast() { + return last; + } + + void PushBack(ASTNode new_node); + void PushFront(ASTNode new_node); + void InsertAfter(ASTNode new_node, ASTNode at_node); + void SetParent(ASTNode new_parent); + void DetachTail(ASTNode node); + void DetachSingle(ASTNode node); + void DetachSegment(ASTNode start, ASTNode end); + void Remove(ASTNode node); + + ASTNode first{}; + ASTNode last{}; +}; + class ASTProgram { public: - ASTProgram() = default; - std::list nodes; + ASTProgram() : nodes{} {}; + ASTZipper nodes; }; -class ASTIf { +class ASTIfThen { public: - ASTIf(Expr condition, std::list then_nodes, std::list else_nodes) - : condition(condition), then_nodes{then_nodes}, else_nodes{then_nodes} {} + ASTIfThen(Expr condition, ASTZipper nodes) : condition(condition), nodes{nodes} {} Expr condition; - std::list then_nodes; - std::list else_nodes; + ASTZipper nodes; +}; + +class ASTIfElse { +public: + ASTIfElse(ASTZipper nodes) : nodes{nodes} {} + ASTZipper nodes; }; class ASTBlockEncoded { @@ -75,10 +114,9 @@ public: class ASTDoWhile { public: - ASTDoWhile(Expr condition, std::list loop_nodes) - : condition(condition), loop_nodes{loop_nodes} {} + ASTDoWhile(Expr condition, ASTZipper nodes) : condition(condition), nodes{nodes} {} Expr condition; - std::list loop_nodes; + ASTZipper nodes; }; class ASTReturn { @@ -88,6 +126,12 @@ public: bool kills; }; +class ASTBreak { +public: + ASTBreak(Expr condition) : condition{condition} {} + Expr condition; +}; + class ASTBase { public: explicit ASTBase(ASTNode parent, ASTData data) : parent{parent}, data{data} {} @@ -111,9 +155,9 @@ public: u32 GetLevel() const { u32 level = 0; - auto next = parent; - while (next) { - next = next->GetParent(); + auto next_parent = parent; + while (next_parent) { + next_parent = next_parent->GetParent(); level++; } return level; @@ -123,15 +167,83 @@ public: return &data; } + ASTNode GetNext() { + return next; + } + + ASTNode GetPrevious() { + return previous; + } + + ASTZipper& GetManager() { + return *manager; + } + + u32 GetGotoLabel() const { + auto inner = std::get_if(&data); + if (inner) { + return inner->label; + } + return -1; + } + + Expr GetGotoCondition() const { + auto inner = std::get_if(&data); + if (inner) { + return inner->condition; + } + return nullptr; + } + + void SetGotoCondition(Expr new_condition) { + auto inner = std::get_if(&data); + if (inner) { + inner->condition = new_condition; + } + } + + bool IsIfThen() const { + return std::holds_alternative(data); + } + + bool IsIfElse() const { + return std::holds_alternative(data); + } + + bool IsLoop() const { + return std::holds_alternative(data); + } + + ASTZipper* GetSubNodes() { + if (std::holds_alternative(data)) { + return &std::get_if(&data)->nodes; + } + if (std::holds_alternative(data)) { + return &std::get_if(&data)->nodes; + } + if (std::holds_alternative(data)) { + return &std::get_if(&data)->nodes; + } + if (std::holds_alternative(data)) { + return &std::get_if(&data)->nodes; + } + return nullptr; + } + private: + friend class ASTZipper; + ASTData data; ASTNode parent; + ASTNode next{}; + ASTNode previous{}; + ASTZipper* manager{}; }; class ASTManager final { public: explicit ASTManager() { - main_node = ASTBase::Make(nullptr); + main_node = ASTBase::Make(ASTNode{}); program = std::get_if(main_node->GetInnerData()); } @@ -147,31 +259,49 @@ public: u32 index = labels_map[address]; ASTNode label = ASTBase::Make(main_node, index); labels[index] = label; - program->nodes.push_back(label); + program->nodes.PushBack(label); } void InsertGoto(Expr condition, u32 address) { u32 index = labels_map[address]; ASTNode goto_node = ASTBase::Make(main_node, condition, index); gotos.push_back(goto_node); - program->nodes.push_back(goto_node); + program->nodes.PushBack(goto_node); } void InsertBlock(u32 start_address, u32 end_address) { ASTNode block = ASTBase::Make(main_node, start_address, end_address); - program->nodes.push_back(block); + program->nodes.PushBack(block); } void InsertReturn(Expr condition, bool kills) { ASTNode node = ASTBase::Make(main_node, condition, kills); - program->nodes.push_back(node); + program->nodes.PushBack(node); } std::string Print(); - void Decompile() {} + void Decompile(); + + private: + bool IndirectlyRelated(ASTNode first, ASTNode second); + + bool DirectlyRelated(ASTNode first, ASTNode second); + + void EncloseDoWhile(ASTNode goto_node, ASTNode label); + + void EncloseIfThen(ASTNode goto_node, ASTNode label); + + void MoveOutward(ASTNode goto_node) ; + + u32 NewVariable() { + u32 new_var = variables; + variables++; + return new_var; + } + std::unordered_map labels_map{}; u32 labels_count{}; std::vector labels{}; -- cgit v1.2.3