]> git.tdb.fi Git - libs/gl.git/commitdiff
Remove unreachable code after a jump statement
authorMikko Rasa <tdb@tdb.fi>
Wed, 7 Apr 2021 20:35:12 +0000 (23:35 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 7 Apr 2021 20:50:26 +0000 (23:50 +0300)
source/glsl/compiler.cpp
source/glsl/optimize.cpp
source/glsl/optimize.h
tests/glsl/dead_code.glsl [new file with mode: 0644]

index 0ad41dfac46c2de102c827e17fa550b421166f3e..e2745e1b9ae41fe6756f7b86204bdd16c86dda10 100644 (file)
@@ -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);
 
index 0f765c2a4aa6ce23edd99f2dd0fed35e4041bd3c..f333ef44b0cfe5ef1a88b26a17203faf1b09ac82 100644 (file)
@@ -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<Statement>::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);
index b7b39176a06e62490573cee96ec174fbcd276ad4..e21dd98fd0fcbe63e578e3012cd072d108c5437d 100644 (file)
@@ -227,6 +227,26 @@ private:
        virtual void visit(Iteration &);
 };
 
+class UnreachableCodeRemover: private TraversingVisitor
+{
+private:
+       bool reachable;
+       std::set<Node *> 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 (file)
index 0000000..bdfd450
--- /dev/null
@@ -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;
+}
+*/