+
+ r_external_side_effects = false;
+ TraversingVisitor::visit(cond);
+
+ if(cond.body.body.empty() && cond.else_body.body.empty() && !r_external_side_effects)
+ nodes_to_remove.insert(&cond);
+}
+
+void ConstantConditionEliminator::visit(Iteration &iter)
+{
+ if(iter.condition)
+ {
+ ConstantStatus result = check_constant_condition(*iter.condition);
+ if(result==CONSTANT_FALSE)
+ {
+ nodes_to_remove.insert(&iter);
+ return;
+ }
+ }
+
+ r_external_side_effects = false;
+ TraversingVisitor::visit(iter);
+ if(iter.body.body.empty() && !r_external_side_effects)
+ nodes_to_remove.insert(&iter);
+}
+
+
+bool UnreachableCodeRemover::apply(Stage &stage)
+{
+ stage.content.visit(*this);
+ NodeRemover().apply(stage, unreachable_nodes);
+ return !unreachable_nodes.empty();
+}
+
+void UnreachableCodeRemover::visit(Block &block)
+{
+ auto 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);
+ NodeRemover().apply(stage, unused_nodes);
+ return !unused_nodes.empty();
+}
+
+void UnusedTypeRemover::visit(RefPtr<Expression> &expr)
+{
+ unused_nodes.erase(expr->type);
+ TraversingVisitor::visit(expr);
+}
+
+void UnusedTypeRemover::visit(BasicTypeDeclaration &type)
+{
+ if(type.base_type)
+ unused_nodes.erase(type.base_type);
+ unused_nodes.insert(&type);
+}
+
+void UnusedTypeRemover::visit(ImageTypeDeclaration &type)
+{
+ if(type.base_type)
+ unused_nodes.erase(type.base_type);
+ unused_nodes.insert(&type);
+}
+
+void UnusedTypeRemover::visit(StructDeclaration &strct)
+{
+ unused_nodes.insert(&strct);
+ TraversingVisitor::visit(strct);
+}
+
+void UnusedTypeRemover::visit(VariableDeclaration &var)
+{