diff options
author | Eric Anholt <[email protected]> | 2010-06-24 08:59:57 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-06-24 13:32:35 -0700 |
commit | f66ba4f3579d69841176bfe7ced9df80eac57a80 (patch) | |
tree | 8c2499bbad3d5ba4503e8fcd742e41d7811a8cda | |
parent | 1b2bcf791365f7bab282e38808efadba19291261 (diff) |
ir_function_inlining: Re-add the "s/return/retval =/" functionality.
I ripped it out with the cloning changes yesterday, and should have
tested and noticed that there were now returns all over.
-rw-r--r-- | ir_function_inlining.cpp | 24 | ||||
-rw-r--r-- | ir_hierarchical_visitor.cpp | 14 | ||||
-rw-r--r-- | ir_hierarchical_visitor.h | 5 |
3 files changed, 41 insertions, 2 deletions
diff --git a/ir_function_inlining.cpp b/ir_function_inlining.cpp index effb01c8f68..d74de650e0a 100644 --- a/ir_function_inlining.cpp +++ b/ir_function_inlining.cpp @@ -91,6 +91,26 @@ do_function_inlining(exec_list *instructions) return v.progress; } +static void +replace_return_with_assignment(ir_instruction *ir, void *data) +{ + ir_variable *retval = (ir_variable *)data; + ir_return *ret = ir->as_return(); + + if (ret) { + if (ret->value) { + ir_rvalue *lhs = new ir_dereference_variable(retval); + ret->insert_before(new ir_assignment(lhs, ret->value, NULL)); + ret->remove(); + } else { + /* un-valued return has to be the last return, or we shouldn't + * have reached here. (see can_inline()). + */ + assert(!ret->next->is_tail_sentinal()); + } + } +} + ir_rvalue * ir_call::generate_inline(ir_instruction *next_ir) { @@ -145,8 +165,10 @@ ir_call::generate_inline(ir_instruction *next_ir) /* Generate the inlined body of the function. */ foreach_iter(exec_list_iterator, iter, callee->body) { ir_instruction *ir = (ir_instruction *)iter.get(); + ir_instruction *new_ir = ir->clone(ht); - next_ir->insert_before(ir->clone(ht)); + next_ir->insert_before(new_ir); + visit_tree(new_ir, replace_return_with_assignment, retval); } /* Copy back the value of any 'out' parameters from the function body diff --git a/ir_hierarchical_visitor.cpp b/ir_hierarchical_visitor.cpp index 63ce8784adb..0d520b127f2 100644 --- a/ir_hierarchical_visitor.cpp +++ b/ir_hierarchical_visitor.cpp @@ -268,3 +268,17 @@ ir_hierarchical_visitor::run(exec_list *instructions) break; } } + + +void +visit_tree(ir_instruction *ir, + void (*callback)(class ir_instruction *ir, void *data), + void *data) +{ + ir_hierarchical_visitor v; + + v.callback = callback; + v.data = data; + + ir->accept(&v); +} diff --git a/ir_hierarchical_visitor.h b/ir_hierarchical_visitor.h index e741155e19f..8b9e49dab13 100644 --- a/ir_hierarchical_visitor.h +++ b/ir_hierarchical_visitor.h @@ -139,7 +139,6 @@ public: */ void run(struct exec_list *instructions); -protected: /** * Callback function that is invoked on entry to each node visited. * @@ -156,4 +155,8 @@ protected: void *data; }; +void visit_tree(ir_instruction *ir, + void (*callback)(class ir_instruction *ir, void *data), + void *data); + #endif /* IR_HIERARCHICAL_VISITOR_H */ |