![]() |
User Guide
|
Visitor to inline local procedure and function calls More...
Visitor to inline local procedure and function calls
Motivation: Mod files often have function and procedure calls. Procedure typically has use of range variables like:
One can reduce the memory bandwidth pressure by inlining rates() and then replacing tau and beta with local variables. Many mod files from BlueBrain and other open source projects could be hugely benefited by inlining pass. The goal of this pass is to implement procedure and function inlining in the nmodl programs. After inlining we should be able to translate AST back to "transformed" nmodl program which can be compiled and run by NEURON or CoreNEURON simulator.
Implementation Notes:
Examples:
The result of inlining :
Definition at line 131 of file inline_visitor.hpp.
#include <inline_visitor.hpp>
Private Member Functions | |
bool | can_replace_statement (const std::shared_ptr< ast::Statement > &statement) |
true if statement can be replaced with inlined body this is possible for standalone function/procedure call as statement More... | |
bool | inline_function_call (ast::Block &callee, ast::FunctionCall &node, ast::StatementBlock &caller) |
inline function/procedure into caller block More... | |
void | inline_arguments (ast::StatementBlock &inlined_block, const ast::ArgumentVector &callee_parameters, const ast::ExpressionVector &caller_expressions) |
add assignment statements into given statement block to inline arguments More... | |
Static Private Member Functions | |
static bool | can_inline_block (const ast::StatementBlock &block) |
true if given statement block can be inlined More... | |
static void | add_return_variable (ast::StatementBlock &block, std::string &varname) |
add assignment statement at end of block (to use as a return statement in case of procedure blocks) More... | |
Private Attributes | |
ast::StatementBlock * | caller_block = nullptr |
statement block containing current function call More... | |
std::shared_ptr< ast::Statement > | caller_statement |
statement containing current function call More... | |
symtab::SymbolTable const * | program_symtab = nullptr |
symbol table for program node More... | |
std::stack< ast::StatementBlock * > | statementblock_stack |
statement blocks in call hierarchy More... | |
std::stack< std::shared_ptr< ast::Statement > > | statement_stack |
statements being executed in call hierarchy More... | |
std::map< std::shared_ptr< ast::Statement >, ast::ExpressionStatement * > | replaced_statements |
map to track the statements being replaces (typically for procedure calls) More... | |
std::map< std::shared_ptr< ast::Statement >, std::vector< std::shared_ptr< ast::ExpressionStatement > > > | inlined_statements |
map to track statements being prepended before function call (typically for function calls) More... | |
std::map< ast::FunctionCall *, std::string > | replaced_fun_calls |
map to track replaced function calls (typically for function calls) More... | |
std::map< std::string, int > | inlined_variables |
variables currently being renamed and their count (for renaming) More... | |
|
default |
|
staticprivate |
add assignment statement at end of block (to use as a return statement in case of procedure blocks)
Definition at line 50 of file inline_visitor.cpp.
|
staticprivate |
true if given statement block can be inlined
inlining is disabled if function/procedure contains table or lag statement
Definition at line 24 of file inline_visitor.cpp.
|
private |
true if statement can be replaced with inlined body this is possible for standalone function/procedure call as statement
We can replace statement if the entire statement itself is a function call.
In this case we check if:
Definition at line 66 of file inline_visitor.cpp.
|
private |
add assignment statements into given statement block to inline arguments
nothing to inline if no arguments for function call
for argument add new variable to local statement
variables in cloned block needs to be renamed
create assignment statement and insert after the local variables
Definition at line 90 of file inline_visitor.cpp.
|
private |
inline function/procedure into caller block
callee | : ast node representing function/procedure definition being called |
node | : function/procedure call node |
caller | : statement block containing function call |
do nothing if we can't inline given procedure/function
make sure to rename conflicting local variable in caller block because in case of procedure inlining they can conflict with global variables used in procedure being inlined
check if caller statement could be replaced
need to add local variable for function calls or for procedure call if it is part of expression (standalone procedure calls don't need return statement)
create new variable which will be used for returning value from inlined block
each block should already have local statement
get a copy of function/procedure body
function definition has function name as return value. we have to rename it with new variable name
each argument is added as new assignment statement
to return value from procedure we have to add new variable
variable name which will replace the function call that we just inlined
Definition at line 128 of file inline_visitor.cpp.
|
overridevirtual |
visit node of type ast::FunctionCall
argument can be function call itself
nothing to do if called function is not defined or it's external
first inline called function
Implements nmodl::visitor::Visitor.
Definition at line 201 of file inline_visitor.cpp.
|
overridevirtual |
visit node of type ast::Program
Implements nmodl::visitor::Visitor.
Definition at line 320 of file inline_visitor.cpp.
|
overridevirtual |
visit node of type ast::StatementBlock
While inlining we have to add new statements before call site. In order to return result we also have to add new local variable to the caller block. Hence we have to keep track of caller block, caller block's symbol table and caller statement.
Add empty local statement at the begining of block if already doesn't exist. Why? When we iterate over statements and inline function call, we have to add local variable to return the result. As we can't modify vector while iterating, we pre-add local statement without any local variables. If inlining pass doesn't add any variable then this statement will be removed.
each block should already have local statement
check if any statement is candidate for replacement due to inlining this is typicall case of procedure calls
all statements from inlining needs to be added before the caller statement
Restore the caller context : consider call chain A() -> B() -> none. When we finishes processing B's statements, even we pop the stack, caller_* variables still point to B's context. Hence first we have to pop elements and then use top() to get context of A(). We have to check for non-empty() stack because if there is only A() -> none then stack is already empty.
Implements nmodl::visitor::Visitor.
Definition at line 234 of file inline_visitor.cpp.
|
overridevirtual |
Visit all wrapped expressions which can contain function calls.
If a function call is replaced then the wrapped expression is also replaced with new variable node from the inlining result.
Implements nmodl::visitor::Visitor.
Definition at line 305 of file inline_visitor.cpp.
|
private |
statement block containing current function call
Definition at line 134 of file inline_visitor.hpp.
|
private |
statement containing current function call
Definition at line 137 of file inline_visitor.hpp.
|
private |
map to track statements being prepended before function call (typically for function calls)
Definition at line 154 of file inline_visitor.hpp.
|
private |
variables currently being renamed and their count (for renaming)
Definition at line 160 of file inline_visitor.hpp.
|
private |
symbol table for program node
Definition at line 140 of file inline_visitor.hpp.
|
private |
map to track replaced function calls (typically for function calls)
Definition at line 157 of file inline_visitor.hpp.
|
private |
map to track the statements being replaces (typically for procedure calls)
Definition at line 149 of file inline_visitor.hpp.
|
private |
statements being executed in call hierarchy
Definition at line 146 of file inline_visitor.hpp.
|
private |
statement blocks in call hierarchy
Definition at line 143 of file inline_visitor.hpp.