source_func = call.declaration->definition;
/* Populate referenced_names from the target function so we can rename
- variables from the inlined function that would conflict. */
+ variables from the inlined function that would conflict. Only consider
+ names which declared in blocks linearly related to the target block. */
pass = REFERENCED;
- target_func.visit(*this);
+ tgt_blk.visit(*this);
+ for(const Block *b=&tgt_blk; b; b=b->parent)
+ for(const auto &kvp: b->variables)
+ referenced_names.insert(kvp.first);
/* Inline and rename passes must be interleaved so used variable names are
known when inlining the return statement. */
ExpressionUse use;
use.reference = &expr;
use.ref_scope = current_block;
- use.blocked = access_write;
+ use.blocked = access_write || r_ref_info->blocked;
if(iteration_body && !r_ref_info->trivial)
{
void ExpressionInliner::visit(UnaryExpression &unary)
{
- SetFlag set_write(access_write, access_write || unary.oper->token[1]=='+' || unary.oper->token[1]=='-');
+ SetFlag set_write(access_write, (unary.oper->token[1]=='+' || unary.oper->token[1]=='-'));
visit(unary.expression);
r_trivial = false;
}
r_trivial = true;
visit(assign.right);
- auto i = assignments.find(assign.target);
+ auto i = assignments.find(assign.target.declaration);
if(i!=assignments.end())
{
- if(iteration_body && i->second->expression)
+ if(iteration_body && i->second && i->second->expression)
{
/* Block inlining into previous references within the iteration
statement. On iterations after the first they would refer to the
u.blocked = (k==iteration_body);
}
+ for(; (i!=assignments.end() && i->first.declaration==assign.target.declaration); ++i)
+ if(targets_overlap(i->first, assign.target))
+ i->second->blocked = true;
+
expressions.push_back(ExpressionInfo());
ExpressionInfo &info = expressions.back();
info.target = assign.target;
info.assign_scope = current_block;
info.trivial = r_trivial;
- i->second = &info;
+ assignments[assign.target] = &info;
}
r_trivial = false;
}
-void ConstantConditionEliminator::apply(Stage &stage)
+bool ConstantConditionEliminator::apply(Stage &stage)
{
stage.content.visit(*this);
NodeRemover().apply(stage, nodes_to_remove);
+ return !nodes_to_remove.empty();
}
ConstantConditionEliminator::ConstantStatus ConstantConditionEliminator::check_constant_condition(const Expression &expr)