From: Mikko Rasa Date: Wed, 7 Apr 2021 20:35:12 +0000 (+0300) Subject: Remove unreachable code after a jump statement X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=55a18f710f07c51f05d0dc55741a7f3cc8e70cdd Remove unreachable code after a jump statement --- diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 0ad41dfa..e2745e1b 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -372,7 +372,8 @@ Compiler::OptimizeResult Compiler::optimize(Stage &stage) /* Removing variables or functions may cause things from the previous stage to become unused. */ - bool any_removed = UnusedVariableRemover().apply(stage); + bool any_removed = UnreachableCodeRemover().apply(stage); + any_removed |= UnusedVariableRemover().apply(stage); any_removed |= UnusedFunctionRemover().apply(stage); any_removed |= UnusedTypeRemover().apply(stage); diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index 0f765c2a..f333ef44 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -907,6 +907,52 @@ void ConstantConditionEliminator::visit(Iteration &iter) } +UnreachableCodeRemover::UnreachableCodeRemover(): + reachable(true) +{ } + +bool UnreachableCodeRemover::apply(Stage &stage) +{ + stage.content.visit(*this); + NodeRemover().apply(stage, unreachable_nodes); + return !unreachable_nodes.empty(); +} + +void UnreachableCodeRemover::visit(Block &block) +{ + NodeList::iterator i = block.body.begin(); + for(; (reachable && i!=block.body.end()); ++i) + (*i)->visit(*this); + for(; i!=block.body.end(); ++i) + unreachable_nodes.insert(i->get()); +} + +void UnreachableCodeRemover::visit(FunctionDeclaration &func) +{ + TraversingVisitor::visit(func); + reachable = true; +} + +void UnreachableCodeRemover::visit(Conditional &cond) +{ + cond.body.visit(*this); + bool reachable_if_true = reachable; + reachable = true; + cond.else_body.visit(*this); + + reachable |= reachable_if_true; +} + +void UnreachableCodeRemover::visit(Iteration &iter) +{ + TraversingVisitor::visit(iter); + + /* Always consider code after a loop reachable, since there's no checking + for whether the loop executes. */ + reachable = true; +} + + bool UnusedTypeRemover::apply(Stage &stage) { stage.content.visit(*this); diff --git a/source/glsl/optimize.h b/source/glsl/optimize.h index b7b39176..e21dd98f 100644 --- a/source/glsl/optimize.h +++ b/source/glsl/optimize.h @@ -227,6 +227,26 @@ private: virtual void visit(Iteration &); }; +class UnreachableCodeRemover: private TraversingVisitor +{ +private: + bool reachable; + std::set unreachable_nodes; + +public: + UnreachableCodeRemover(); + + virtual bool apply(Stage &); + +private: + virtual void visit(Block &); + virtual void visit(FunctionDeclaration &); + virtual void visit(Conditional &); + virtual void visit(Iteration &); + virtual void visit(Return &) { reachable = false; } + virtual void visit(Jump &) { reachable = false; } +}; + /** Removes types which are not used anywhere. */ class UnusedTypeRemover: private TraversingVisitor { diff --git a/tests/glsl/dead_code.glsl b/tests/glsl/dead_code.glsl new file mode 100644 index 00000000..bdfd4503 --- /dev/null +++ b/tests/glsl/dead_code.glsl @@ -0,0 +1,20 @@ +uniform mat4 mvp; + +#pragma MSP stage(vertex) +layout(location=0) in vec4 position; +void main() +{ + gl_Position = mvp*position; + return; + gl_Position = position; +} + +/* Expected output: vertex +layout(location=0) uniform mat4 mvp; +layout(location=0) in vec4 position; +void main() +{ + gl_Position = mvp*position; + return; +} +*/