+
+ /* Only inline global variables if they're constant and have trivial
+ initializers. Non-constant variables could change in ways which are hard to
+ analyze and non-trivial expressions could be expensive to inline. */
+ if((current_block->parent || (constant && r_trivial)) && var.interface.empty())
+ {
+ ExpressionInfo &info = expressions[&var];
+ /* Assume variables declared in an iteration initialization statement
+ will have their values change throughout the iteration. */
+ info.expression = (iteration_init ? 0 : var.init_expression.get());
+ info.assign_scope = current_block;
+ info.inner_oper = r_oper;
+ info.trivial = r_trivial;
+ }
+}
+
+void ExpressionInliner::visit(Conditional &cond)
+{
+ visit_and_record(cond.condition, 0, false);
+ cond.body.visit(*this);
+}
+
+void ExpressionInliner::visit(Iteration &iter)
+{
+ SetForScope<Block *> set_block(current_block, &iter.body);
+ if(iter.init_statement)
+ {
+ SetFlag set_init(iteration_init);
+ iter.init_statement->visit(*this);
+ }
+
+ SetForScope<Block *> set_body(iteration_body, &iter.body);
+ if(iter.condition)
+ iter.condition->visit(*this);
+ iter.body.visit(*this);
+ if(iter.loop_expression)
+ iter.loop_expression->visit(*this);
+}
+
+void ExpressionInliner::visit(Return &ret)
+{
+ if(ret.expression)
+ visit_and_record(ret.expression, 0, false);
+}
+
+
+void ConstantConditionEliminator::apply(Stage &stage)
+{
+ stage.content.visit(*this);
+ NodeRemover().apply(stage, nodes_to_remove);
+}
+
+void ConstantConditionEliminator::visit(Block &block)
+{
+ SetForScope<Block *> set_block(current_block, &block);
+ for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
+ {
+ insert_point = i;
+ (*i)->visit(*this);
+ }