From 4cb06c8a344da9c5673bf043bf81f60e145743e3 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 2 Mar 2017 18:37:43 +0100 Subject: [PATCH] support inlining of non-outermost call expressions Commit 253cd82 (support inlining of outermost call expressions, Tue Aug 11 14:10:38 2015 +0200) introduced support for inlining outermost call expression. Allow inlining outer call expressions as well. In particular, allow inlined functions to have a return statement at the end and replace this return statement by a write to a freshly created variable. The calls in the original statement and in arguments to outer inlined functions are replaced by reads from these variables. Signed-off-by: Sven Verdoolaege --- Makefile.am | 2 + inlined_calls.cc | 155 +++++++++++++++++++++++ inlined_calls.h | 40 ++++++ inliner.cc | 63 +++++++++- inliner.h | 3 +- scan.cc | 51 +++++--- scan.h | 12 +- tests/inline12.c | 13 ++ tests/inline12.scop | 352 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/inline13.c | 13 ++ tests/inline13.scop | 246 ++++++++++++++++++++++++++++++++++++ tests/inline14.c | 17 +++ tests/inline14.scop | 208 +++++++++++++++++++++++++++++++ 13 files changed, 1156 insertions(+), 19 deletions(-) create mode 100644 inlined_calls.cc create mode 100644 inlined_calls.h create mode 100644 tests/inline12.c create mode 100644 tests/inline12.scop create mode 100644 tests/inline13.c create mode 100644 tests/inline13.scop create mode 100644 tests/inline14.c create mode 100644 tests/inline14.scop diff --git a/Makefile.am b/Makefile.am index 0e38c22..3b72335 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,6 +68,8 @@ libpet_la_SOURCES = \ filter.c \ id.h \ id.cc \ + inlined_calls.h \ + inlined_calls.cc \ inliner.h \ inliner.cc \ isl_id_to_pet_expr.h \ diff --git a/inlined_calls.cc b/inlined_calls.cc new file mode 100644 index 0000000..c54991b --- /dev/null +++ b/inlined_calls.cc @@ -0,0 +1,155 @@ +/* + * Copyright 2017 Sven Verdoolaege. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as + * representing official policies, either expressed or implied, of + * Sven Verdoolaege. + */ + +#include "clang.h" +#include "expr_plus.h" +#include "id.h" +#include "inlined_calls.h" +#include "scan.h" +#include "tree.h" + +using namespace std; +using namespace clang; + +pet_inlined_calls::~pet_inlined_calls() +{ + vector::iterator it; + map::iterator it_id; + + for (it = inlined.begin(); it != inlined.end(); ++it) + pet_tree_free(*it); + for (it_id = call2id.begin(); it_id != call2id.end(); ++it_id) + isl_id_free(it_id->second); +} + +/* This method is called for each call expression "call" + * in an expression statement. + * + * If the corresponding function body is marked "inline", then add + * it to this->calls. + * + * Return true to continue the traversal. + */ +bool pet_inlined_calls::VisitCallExpr(clang::CallExpr *call) +{ + FunctionDecl *fd = call->getDirectCallee(); + + fd = pet_clang_find_function_decl_with_body(fd); + + if (fd && fd->isInlineSpecified()) + calls.push_back(call); + + return true; +} + +/* Extract a pet_tree corresponding to the inlined function that + * is called by "call" and store it in this->inlined. + * If, moreover, the inlined function has a return value, + * then create a corresponding variable and store it in this->call2id. + * + * While extracting the inlined function, take into account + * the mapping from call expressions to return variables for + * previously extracted inlined functions in order to handle + * nested calls. + */ +void pet_inlined_calls::add(CallExpr *call) +{ + FunctionDecl *fd = call->getDirectCallee(); + QualType qt; + isl_id *id = NULL; + + qt = fd->getReturnType(); + if (!qt->isVoidType()) { + id = pet_id_ret_from_type(scan->ctx, scan->n_ret++, qt); + call2id[call] = isl_id_copy(id); + } + scan->call2id = &this->call2id; + inlined.push_back(scan->extract_inlined_call(call, fd, id)); + scan->call2id = NULL; + isl_id_free(id); +} + +/* Collect all the call expressions in "stmt" that need to be inlined, + * the corresponding pet_tree objects and the variables that store + * the return values. + * + * The call expressions are first collected outermost to innermost. + * Then the corresponding inlined functions are extracted in reverse order + * to ensure that a nested call is performed before an outer call. + */ +void pet_inlined_calls::collect(Stmt *stmt) +{ + int n; + + TraverseStmt(stmt); + + n = calls.size(); + for (int i = n - 1; i >= 0; --i) + add(cast(calls[i])); +} + +/* Add the inlined call expressions to "tree", where "tree" corresponds + * to the original expression statement containing the calls, but with + * the calls replaced by accesses to the return variables in this->call2id. + * In particular, construct a new block containing declarations + * for the return variables in this->call2id, the inlined functions + * from innermost to outermost and finally "tree" itself. + */ +__isl_give pet_tree *pet_inlined_calls::add_inlined(__isl_take pet_tree *tree) +{ + pet_tree *block; + int n; + std::vector::iterator it_in; + std::map::iterator it; + + if (inlined.empty()) + return tree; + + n = call2id.size() + inlined.size() + 1; + + block = pet_tree_new_block(scan->ctx, 1, n); + for (it = call2id.begin(); it != call2id.end(); ++it) { + pet_expr *expr; + pet_tree *decl; + + expr = pet_expr_access_from_id(isl_id_copy(it->second), + scan->ast_context); + decl = pet_tree_new_decl(expr); + block = pet_tree_block_add_child(block, decl); + } + for (it_in = inlined.begin(); it_in != inlined.end(); ++it_in) + block = pet_tree_block_add_child(block, pet_tree_copy(*it_in)); + block = pet_tree_block_add_child(block, tree); + + return block; +} diff --git a/inlined_calls.h b/inlined_calls.h new file mode 100644 index 0000000..171bf5c --- /dev/null +++ b/inlined_calls.h @@ -0,0 +1,40 @@ +#ifndef PET_INLINED_CALLS_H +#define PET_INLINED_CALLS_H + +#include +#include + +#include +#include +#include +#include + +struct PetScan; + +/* Structure for keeping track of inlined calls in an expression statement. + * + * "calls" collects the calls that appear in the expression statement and + * that need to be inlined from outermost to innermost. + * "inlined" collects the inlined pet_tree objects corresponding to elements + * in "calls" in reverse order. + * "call2id" maps inlined call expressions that return a value to + * the corresponding variable. + * "scan" is used to extract the inlined calls. + */ +struct pet_inlined_calls : clang::RecursiveASTVisitor { + std::vector calls; + std::vector inlined; + std::map call2id; + PetScan *scan; + + pet_inlined_calls(PetScan *scan) : scan(scan) {} + ~pet_inlined_calls(); + + bool VisitCallExpr(clang::CallExpr *call); + + void add(clang::CallExpr *call); + void collect(clang::Stmt *stmt); + __isl_give pet_tree *add_inlined(__isl_take pet_tree *tree); +}; + +#endif diff --git a/inliner.cc b/inliner.cc index 81a1091..044fe3b 100644 --- a/inliner.cc +++ b/inliner.cc @@ -1,6 +1,6 @@ /* * Copyright 2011 Leiden University. All rights reserved. - * Copyright 2015 Sven Verdoolaege. All rights reserved. + * Copyright 2015,2017 Sven Verdoolaege. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,10 +110,67 @@ void pet_inliner::add_array_arg(ValueDecl *decl, __isl_take pet_expr *expr, add_sub(id, expr); } +/* Data needed in replace_return_base pet_tree_map_top_down callback. + */ +struct replace_return_data { + clang::ASTContext &ast_context; + isl_id *return_id; + + replace_return_data(clang::ASTContext &ast_context, isl_id *return_id) : + ast_context(ast_context), return_id(return_id) {} +}; + +extern "C" { + static __isl_give pet_tree *replace_return_base( + __isl_take pet_tree *tree, void *user); +} + +/* This function is called for every subtree of a pet_tree. + * If the subtree corresponds to a return statement, + * then replace the return statement by an assignment + * of the returned expression to data->return_id. + */ +static __isl_give pet_tree *replace_return_base(__isl_take pet_tree *tree, + void *user) +{ + replace_return_data *data = (replace_return_data *) user; + int type_size; + pet_expr *var; + pet_expr *expr; + + if (pet_tree_get_type(tree) != pet_tree_return) + return tree; + + expr = pet_tree_return_get_expr(tree); + pet_tree_free(tree); + + var = pet_expr_access_from_id(isl_id_copy(data->return_id), + data->ast_context); + type_size = pet_expr_get_type_size(var); + var = pet_expr_access_set_write(var, 1); + var = pet_expr_access_set_read(var, 0); + + expr = pet_expr_new_binary(type_size, pet_op_assign, var, expr); + + return pet_tree_new_expr(expr); +} + +/* Replace any return statement in "tree" by a write to "return_id". + */ +static __isl_give pet_tree *replace_return(__isl_take pet_tree *tree, + clang::ASTContext &ast_context, __isl_keep isl_id *return_id) +{ + replace_return_data data(ast_context, return_id); + return pet_tree_map_top_down(tree, &replace_return_base, &data); +} + /* Inline "tree" by applying the substitutions to "tree" and placing * the result in a block after the assignments stored in "assignments". + * If "return_id" is not NULL, then any return statement in "tree" + * is replaced by a write to "return_id". */ -__isl_give pet_tree *pet_inliner::inline_tree(__isl_take pet_tree *tree) +__isl_give pet_tree *pet_inliner::inline_tree(__isl_take pet_tree *tree, + __isl_keep isl_id *return_id) { pet_expr *expr; pet_tree *block; @@ -133,6 +190,8 @@ __isl_give pet_tree *pet_inliner::inline_tree(__isl_take pet_tree *tree) } tree = substitute(tree); + if (return_id) + tree = replace_return(tree, ast_context, return_id); block = pet_tree_block_add_child(block, tree); return block; diff --git a/inliner.h b/inliner.h index a5fe9c7..68440bd 100644 --- a/inliner.h +++ b/inliner.h @@ -56,7 +56,8 @@ struct pet_inliner : pet_substituter { void add_array_arg(clang::ValueDecl *decl, __isl_take pet_expr *expr, int is_add); - __isl_give pet_tree *inline_tree(__isl_take pet_tree *tree); + __isl_give pet_tree *inline_tree(__isl_take pet_tree *tree, + __isl_keep isl_id *return_id); ~pet_inliner(); }; diff --git a/scan.cc b/scan.cc index c4451fc..212311d 100644 --- a/scan.cc +++ b/scan.cc @@ -61,6 +61,7 @@ #include "expr_plus.h" #include "id.h" #include "inliner.h" +#include "inlined_calls.h" #include "killed_locals.h" #include "nest.h" #include "options.h" @@ -996,6 +997,11 @@ static bool is_assume(int pencil, const string &name) /* Construct a pet_expr representing a function call. * + * If this->call2id is not NULL and it contains a mapping for this call, + * then this means that the corresponding function has been inlined. + * Return a pet_expr that reads from the variable that + * stores the return value of the inlined call. + * * In the special case of a "call" to __builtin_assume or __pencil_assume, * construct an assume expression instead. * @@ -1014,6 +1020,10 @@ __isl_give pet_expr *PetScan::extract_expr(CallExpr *expr) unsigned n_arg; bool is_kill; + if (call2id && call2id->find(expr) != call2id->end()) + return pet_expr_access_from_id(isl_id_copy(call2id[0][expr]), + ast_context); + fd = expr->getDirectCallee(); if (!fd) { unsupported(expr); @@ -1940,12 +1950,16 @@ int PetScan::substitute_array_sizes(__isl_keep pet_tree *tree, * of (parts of) the actual arguments to temporary variables * followed by the inlined function body with the formal arguments * replaced by (expressions containing) these temporary variables. + * If "return_id" is set, then it is used to store the return value + * of the inlined function. * * The actual inlining is taken care of by the pet_inliner object. * This function merely calls set_inliner_arguments to tell * the pet_inliner about the actual arguments, extracts a pet_tree * from the body of the called function and then passes this pet_tree * to the pet_inliner. + * The body of the called function is allowed to have a return statement + * at the end. * The substitutions performed by the inliner are also applied * to the size expressions of the arrays declared in the inlined * function. These size expressions are not stored in the tree @@ -1963,7 +1977,7 @@ int PetScan::substitute_array_sizes(__isl_keep pet_tree *tree, * function. */ __isl_give pet_tree *PetScan::extract_inlined_call(CallExpr *call, - FunctionDecl *fd) + FunctionDecl *fd, __isl_keep isl_id *return_id) { int save_autodetect; pet_tree *tree; @@ -1980,6 +1994,7 @@ __isl_give pet_tree *PetScan::extract_inlined_call(CallExpr *call, collect_declared_names(); body_scan.add_new_used_names(declared_names); body_scan.add_new_used_names(used_names); + body_scan.return_root = fd->getBody(); tree = body_scan.extract(fd->getBody(), false); add_new_used_names(body_scan.used_names); options->autodetect = save_autodetect; @@ -1989,30 +2004,38 @@ __isl_give pet_tree *PetScan::extract_inlined_call(CallExpr *call, substitute_array_sizes(tree, &inliner); - return inliner.inline_tree(tree); + return inliner.inline_tree(tree, return_id); } /* Try and construct a pet_tree corresponding * to the expression statement "stmt". * - * If the outer expression is a function call and if the corresponding - * function body is marked "inline", then return a pet_tree - * corresponding to the inlined function. + * First look for function calls that have corresponding bodies + * marked "inline". Extract the inlined functions in a pet_inlined_calls + * object. Then extract the statement itself, replacing calls + * to inlined function by accesses to the corresponding return variables, and + * return the combined result. + * If the outer expression is itself a call to an inlined function, + * then it already appears as one of the inlined functions and + * no separate pet_tree needs to be extracted for "stmt" itself. */ __isl_give pet_tree *PetScan::extract_expr_stmt(Stmt *stmt) { pet_expr *expr; + pet_tree *tree; + pet_inlined_calls ic(this); - if (stmt->getStmtClass() == Stmt::CallExprClass) { - CallExpr *call = cast(stmt); - FunctionDecl *fd = call->getDirectCallee(); - fd = pet_clang_find_function_decl_with_body(fd); - if (fd && fd->isInlineSpecified()) - return extract_inlined_call(call, fd); + ic.collect(stmt); + if (ic.calls.size() >= 1 && ic.calls[0] == stmt) { + tree = pet_tree_new_block(ctx, 0, 0); + } else { + call2id = &ic.call2id; + expr = extract_expr(cast(stmt)); + tree = extract(expr, stmt->getSourceRange(), true); + call2id = NULL; } - - expr = extract_expr(cast(stmt)); - return extract(expr, stmt->getSourceRange(), true); + tree = ic.add_inlined(tree); + return tree; } /* Try and construct a pet_tree corresponding to "stmt". diff --git a/scan.h b/scan.h index aa025dc..46eb2b9 100644 --- a/scan.h +++ b/scan.h @@ -154,8 +154,15 @@ struct PetScan { /* A set of names known to be in use. */ std::set used_names; + /* If not NULL, then "call2id" maps inlined call expressions + * that return a value to the corresponding variables. + */ + std::map *call2id; + /* Sequence number of the next temporary inlined argument variable. */ int n_arg; + /* Sequence number of the next temporary inlined return variable. */ + int n_ret; PetScan(clang::Preprocessor &PP, clang::ASTContext &ast_context, clang::DeclContext *decl_context, ScopLoc &loc, @@ -167,7 +174,8 @@ struct PetScan { options(options), return_root(NULL), partial(false), value_bounds(value_bounds), last_line(0), current_line(0), independent(independent), n_rename(0), - declared_names_collected(false), n_arg(0) { + declared_names_collected(false), call2id(NULL), + n_arg(0), n_ret(0) { id_size = isl_id_to_pet_expr_alloc(ctx, 0); } @@ -182,7 +190,7 @@ struct PetScan { struct pet_array *extract_array(__isl_keep isl_id *id, PetTypes *types, __isl_keep pet_context *pc); __isl_give pet_tree *extract_inlined_call(clang::CallExpr *call, - clang::FunctionDecl *fd); + clang::FunctionDecl *fd, __isl_keep isl_id *return_id); private: void set_current_stmt(clang::Stmt *stmt); bool is_current_stmt_marked_independent(); diff --git a/tests/inline12.c b/tests/inline12.c new file mode 100644 index 0000000..c28b497 --- /dev/null +++ b/tests/inline12.c @@ -0,0 +1,13 @@ +inline int select(int n, int a[n], int i) +{ + return a[i]; +} + +void foo(int n, int a[n]) +{ +#pragma scop + for (int i = 0; i + 1 < n; ++i) { + a[i] = select(n, a, i) + select(n, a, i + 1); + } +#pragma endscop +} diff --git a/tests/inline12.scop b/tests/inline12.scop new file mode 100644 index 0000000..e1e8ef5 --- /dev/null +++ b/tests/inline12.scop @@ -0,0 +1,352 @@ +start: 89 +end: 204 +indent: "\t" +context: '[n] -> { : -2147483648 <= n <= 2147483647 }' +schedule: '{ domain: "[n] -> { S_7[i] : 0 <= i <= -2 + n; S_6[i] : 0 <= i <= -2 + + n; S_14[i] : 0 <= i <= -2 + n; S_4[i] : 0 <= i <= -2 + n; S_8[i] : 0 <= i <= -2 + + n; S_12[i] : 0 <= i <= -2 + n; S_11[i] : 0 <= i <= -2 + n; S_15[i] : 0 <= i <= + -2 + n; S_16[i] : 0 <= i <= -2 + n; S_2[i] : 0 <= i <= -2 + n; S_3[i] : 0 <= i <= + -2 + n; S_5[i] : 0 <= i <= -2 + n; S_17[i] : 0 <= i <= -2 + n; S_13[i] : 0 <= i + <= -2 + n; S_1[i] : 0 <= i <= -2 + n; S_10[i] : 0 <= i <= -2 + n; S_0[i] : 0 <= + i <= -2 + n; S_9[i] : 0 <= i <= -2 + n; S_18[i] : 0 <= i <= -2 + n }", child: { + schedule: "[n] -> L_0[{ S_7[i] -> [(i)]; S_6[i] -> [(i)]; S_14[i] -> [(i)]; S_4[i] + -> [(i)]; S_8[i] -> [(i)]; S_12[i] -> [(i)]; S_11[i] -> [(i)]; S_15[i] -> [(i)]; + S_16[i] -> [(i)]; S_2[i] -> [(i)]; S_3[i] -> [(i)]; S_5[i] -> [(i)]; S_17[i] -> + [(i)]; S_13[i] -> [(i)]; S_1[i] -> [(i)]; S_10[i] -> [(i)]; S_0[i] -> [(i)]; S_9[i] + -> [(i)]; S_18[i] -> [(i)] }]", child: { sequence: [ { filter: "[n] -> { S_0[i] + }" }, { filter: "[n] -> { S_2[i] }" }, { filter: "[n] -> { S_4[i] }" }, { filter: + "[n] -> { S_5[i] }" }, { filter: "[n] -> { S_7[i] }" }, { filter: "[n] -> { S_8[i] + }" }, { filter: "[n] -> { S_10[i] }" }, { filter: "[n] -> { S_6[i]; S_9[i] }", child: + { set: [ { filter: "[n] -> { S_6[i] }" }, { filter: "[n] -> { S_9[i] }" } ] } }, + { filter: "[n] -> { S_11[i] }" }, { filter: "[n] -> { S_12[i] }" }, { filter: "[n] + -> { S_14[i] }" }, { filter: "[n] -> { S_15[i] }" }, { filter: "[n] -> { S_17[i] + }" }, { filter: "[n] -> { S_16[i]; S_13[i] }", child: { set: [ { filter: "[n] -> + { S_13[i] }" }, { filter: "[n] -> { S_16[i] }" } ] } }, { filter: "[n] -> { S_18[i] + }" }, { filter: "[n] -> { S_3[i]; S_1[i] }", child: { set: [ { filter: "[n] -> { + S_1[i] }" }, { filter: "[n] -> { S_3[i] }" } ] } } ] } } }' +arrays: +- context: '{ : }' + extent: '[n] -> { __pet_ret_1[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { __pet_ret_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { n_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { i_1[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { n_2[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { i_3[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { a[i0] : i0 >= 0 }' + element_type: int + element_size: 4 +statements: +- line: -1 + domain: '[n] -> { S_0[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_0[i] -> __pet_ret_1[] }' + index: '[n] -> { S_0[i] -> __pet_ret_1[] }' + reference: __pet_ref_0 + kill: 1 +- line: -1 + domain: '[n] -> { S_2[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_2[i] -> __pet_ret_0[] }' + index: '[n] -> { S_2[i] -> __pet_ret_0[] }' + reference: __pet_ref_1 + kill: 1 +- line: -1 + domain: '[n] -> { S_4[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_4[i] -> n_0[] }' + index: '[n] -> { S_4[i] -> n_0[] }' + reference: __pet_ref_2 + kill: 1 +- line: -1 + domain: '[n] -> { S_5[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_5[i] -> n_0[] }' + reference: __pet_ref_3 + read: 0 + write: 1 + - type: access + index: '[n] -> { S_5[i] -> [(n)] }' + reference: __pet_ref_4 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_7[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_7[i] -> i_1[] }' + index: '[n] -> { S_7[i] -> i_1[] }' + reference: __pet_ref_5 + kill: 1 +- line: -1 + domain: '[n] -> { S_8[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_8[i] -> i_1[] }' + reference: __pet_ref_6 + read: 0 + write: 1 + - type: access + index: '[n] -> { S_8[i] -> [(1 + i)] }' + reference: __pet_ref_7 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_10[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_10[i] -> __pet_ret_0[] }' + reference: __pet_ref_8 + read: 0 + write: 1 + - type: access + index: '[n] -> { S_10[i] -> a[(1 + i)] }' + reference: __pet_ref_9 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_6[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_6[i] -> n_0[] }' + index: '[n] -> { S_6[i] -> n_0[] }' + reference: __pet_ref_10 + kill: 1 +- line: -1 + domain: '[n] -> { S_9[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_9[i] -> i_1[] }' + index: '[n] -> { S_9[i] -> i_1[] }' + reference: __pet_ref_11 + kill: 1 +- line: -1 + domain: '[n] -> { S_11[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_11[i] -> n_2[] }' + index: '[n] -> { S_11[i] -> n_2[] }' + reference: __pet_ref_12 + kill: 1 +- line: -1 + domain: '[n] -> { S_12[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_12[i] -> n_2[] }' + reference: __pet_ref_13 + read: 0 + write: 1 + - type: access + index: '[n] -> { S_12[i] -> [(n)] }' + reference: __pet_ref_14 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_14[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_14[i] -> i_3[] }' + index: '[n] -> { S_14[i] -> i_3[] }' + reference: __pet_ref_15 + kill: 1 +- line: -1 + domain: '[n] -> { S_15[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_15[i] -> i_3[] }' + reference: __pet_ref_16 + read: 0 + write: 1 + - type: access + index: '[n] -> { S_15[i] -> [(i)] }' + reference: __pet_ref_17 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_17[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_17[i] -> __pet_ret_1[] }' + reference: __pet_ref_18 + read: 0 + write: 1 + - type: access + index: '[n] -> { S_17[i] -> a[(i)] }' + reference: __pet_ref_19 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_13[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_13[i] -> n_2[] }' + index: '[n] -> { S_13[i] -> n_2[] }' + reference: __pet_ref_20 + kill: 1 +- line: -1 + domain: '[n] -> { S_16[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_16[i] -> i_3[] }' + index: '[n] -> { S_16[i] -> i_3[] }' + reference: __pet_ref_21 + kill: 1 +- line: 10 + domain: '[n] -> { S_18[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[n] -> { S_18[i] -> a[(i)] }' + reference: __pet_ref_22 + read: 0 + write: 1 + - type: op + operation: + + arguments: + - type: access + index: '[n] -> { S_18[i] -> __pet_ret_1[] }' + reference: __pet_ref_23 + read: 1 + write: 0 + - type: access + index: '[n] -> { S_18[i] -> __pet_ret_0[] }' + reference: __pet_ref_24 + read: 1 + write: 0 +- line: -1 + domain: '[n] -> { S_1[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_1[i] -> __pet_ret_1[] }' + index: '[n] -> { S_1[i] -> __pet_ret_1[] }' + reference: __pet_ref_25 + kill: 1 +- line: -1 + domain: '[n] -> { S_3[i] : 0 <= i <= -2 + n }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[n] -> { S_3[i] -> __pet_ret_0[] }' + index: '[n] -> { S_3[i] -> __pet_ret_0[] }' + reference: __pet_ref_26 + kill: 1 diff --git a/tests/inline13.c b/tests/inline13.c new file mode 100644 index 0000000..9f742cf --- /dev/null +++ b/tests/inline13.c @@ -0,0 +1,13 @@ +inline int add_one(int i) +{ + return i + 1; +} + +void foo() +{ + int a; + +#pragma scop + a = add_one(add_one(5)); +#pragma endscop +} diff --git a/tests/inline13.scop b/tests/inline13.scop new file mode 100644 index 0000000..b1e4f92 --- /dev/null +++ b/tests/inline13.scop @@ -0,0 +1,246 @@ +start: 68 +end: 123 +indent: +context: '{ : }' +schedule: '{ domain: "{ S_3[]; S_10[]; S_0[]; S_5[]; S_12[]; S_11[]; S_7[]; S_13[]; + S_6[]; S_8[]; S_9[]; S_2[]; S_4[]; S_1[] }", child: { sequence: [ { filter: "{ S_0[] + }" }, { filter: "{ S_2[] }" }, { filter: "{ S_4[] }" }, { filter: "{ S_5[] }" }, + { filter: "{ S_7[] }" }, { filter: "{ S_6[] }" }, { filter: "{ S_8[] }" }, { filter: + "{ S_9[] }" }, { filter: "{ S_11[] }" }, { filter: "{ S_10[] }" }, { filter: "{ + S_12[] }" }, { filter: "{ S_3[]; S_1[] }", child: { set: [ { filter: "{ S_1[] }" + }, { filter: "{ S_3[] }" } ] } }, { filter: "{ S_13[] }" } ] } }' +arrays: +- context: '{ : }' + extent: '{ __pet_ret_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '{ __pet_ret_1[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '{ i[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '{ i_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '{ a[] }' + element_type: int + element_size: 4 +statements: +- line: -1 + domain: '{ S_0[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_0[] -> __pet_ret_0[] }' + index: '{ S_0[] -> __pet_ret_0[] }' + reference: __pet_ref_0 + kill: 1 +- line: -1 + domain: '{ S_2[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_2[] -> __pet_ret_1[] }' + index: '{ S_2[] -> __pet_ret_1[] }' + reference: __pet_ref_1 + kill: 1 +- line: -1 + domain: '{ S_4[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_4[] -> i[] }' + index: '{ S_4[] -> i[] }' + reference: __pet_ref_2 + kill: 1 +- line: -1 + domain: '{ S_5[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_5[] -> i[] }' + reference: __pet_ref_3 + read: 0 + write: 1 + - type: int + value: 5 +- line: -1 + domain: '{ S_7[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_7[] -> __pet_ret_0[] }' + reference: __pet_ref_4 + read: 0 + write: 1 + - type: access + index: '{ S_7[] -> [(6)] }' + reference: __pet_ref_5 + read: 1 + write: 0 +- line: -1 + domain: '{ S_6[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_6[] -> i[] }' + index: '{ S_6[] -> i[] }' + reference: __pet_ref_6 + kill: 1 +- line: -1 + domain: '{ S_8[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_8[] -> i_0[] }' + index: '{ S_8[] -> i_0[] }' + reference: __pet_ref_7 + kill: 1 +- line: -1 + domain: '{ S_9[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_9[] -> i_0[] }' + reference: __pet_ref_8 + read: 0 + write: 1 + - type: access + index: '{ S_9[] -> __pet_ret_0[] }' + reference: __pet_ref_9 + read: 1 + write: 0 +- line: -1 + domain: '{ S_11[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_11[] -> __pet_ret_1[] }' + reference: __pet_ref_10 + read: 0 + write: 1 + - type: op + operation: + + arguments: + - type: access + index: '{ S_11[] -> i_0[] }' + reference: __pet_ref_11 + read: 1 + write: 0 + - type: int + value: 1 +- line: -1 + domain: '{ S_10[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_10[] -> i_0[] }' + index: '{ S_10[] -> i_0[] }' + reference: __pet_ref_12 + kill: 1 +- line: 11 + domain: '{ S_12[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_12[] -> a[] }' + reference: __pet_ref_13 + read: 0 + write: 1 + - type: access + index: '{ S_12[] -> __pet_ret_1[] }' + reference: __pet_ref_14 + read: 1 + write: 0 +- line: -1 + domain: '{ S_1[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_1[] -> __pet_ret_0[] }' + index: '{ S_1[] -> __pet_ret_0[] }' + reference: __pet_ref_15 + kill: 1 +- line: -1 + domain: '{ S_3[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_3[] -> __pet_ret_1[] }' + index: '{ S_3[] -> __pet_ret_1[] }' + reference: __pet_ref_16 + kill: 1 +- line: -1 + domain: '{ S_13[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_13[] -> a[] }' + index: '{ S_13[] -> a[] }' + reference: __pet_ref_17 + kill: 1 diff --git a/tests/inline14.c b/tests/inline14.c new file mode 100644 index 0000000..e5a5fd6 --- /dev/null +++ b/tests/inline14.c @@ -0,0 +1,17 @@ +inline void g(int a) +{ + a += 1; +} + +inline int h(int a) +{ + return a + 1; +} + +void f() +{ +#pragma scop + int a = 1; + g(h(a)); +#pragma endscop +} diff --git a/tests/inline14.scop b/tests/inline14.scop new file mode 100644 index 0000000..9799724 --- /dev/null +++ b/tests/inline14.scop @@ -0,0 +1,208 @@ +start: 86 +end: 137 +indent: "\t" +context: '{ : }' +schedule: '{ domain: "{ S_3[]; S_10[]; S_0[]; S_5[]; S_11[]; S_7[]; S_6[]; S_8[]; + S_9[]; S_2[]; S_1[]; S_4[] }", child: { sequence: [ { filter: "{ S_0[] }" }, { filter: + "{ S_1[] }" }, { filter: "{ S_2[] }" }, { filter: "{ S_4[] }" }, { filter: "{ S_5[] + }" }, { filter: "{ S_7[] }" }, { filter: "{ S_6[] }" }, { filter: "{ S_8[] }" }, + { filter: "{ S_9[] }" }, { filter: "{ S_11[] }" }, { filter: "{ S_10[] }" }, { filter: + "{ S_3[] }" } ] } }' +arrays: +- context: '{ : }' + extent: '{ a[] }' + element_type: int + element_size: 4 + declared: 1 + exposed: 1 +- context: '{ : }' + extent: '{ __pet_ret_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '{ a_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '{ a_1[] }' + element_type: int + element_size: 4 + declared: 1 +statements: +- line: 14 + domain: '{ S_0[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_0[] -> a[] }' + index: '{ S_0[] -> a[] }' + reference: __pet_ref_0 + kill: 1 +- line: 14 + domain: '{ S_1[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_1[] -> a[] }' + reference: __pet_ref_1 + read: 0 + write: 1 + - type: int + value: 1 +- line: -1 + domain: '{ S_2[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_2[] -> __pet_ret_0[] }' + index: '{ S_2[] -> __pet_ret_0[] }' + reference: __pet_ref_2 + kill: 1 +- line: -1 + domain: '{ S_4[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_4[] -> a_0[] }' + index: '{ S_4[] -> a_0[] }' + reference: __pet_ref_3 + kill: 1 +- line: -1 + domain: '{ S_5[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_5[] -> a_0[] }' + reference: __pet_ref_4 + read: 0 + write: 1 + - type: access + index: '{ S_5[] -> [(1)] }' + reference: __pet_ref_5 + read: 1 + write: 0 +- line: -1 + domain: '{ S_7[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_7[] -> __pet_ret_0[] }' + reference: __pet_ref_6 + read: 0 + write: 1 + - type: access + index: '{ S_7[] -> [(2)] }' + reference: __pet_ref_7 + read: 1 + write: 0 +- line: -1 + domain: '{ S_6[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_6[] -> a_0[] }' + index: '{ S_6[] -> a_0[] }' + reference: __pet_ref_8 + kill: 1 +- line: -1 + domain: '{ S_8[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_8[] -> a_1[] }' + index: '{ S_8[] -> a_1[] }' + reference: __pet_ref_9 + kill: 1 +- line: -1 + domain: '{ S_9[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '{ S_9[] -> a_1[] }' + reference: __pet_ref_10 + read: 0 + write: 1 + - type: access + index: '{ S_9[] -> __pet_ret_0[] }' + reference: __pet_ref_11 + read: 1 + write: 0 +- line: 3 + domain: '{ S_11[] }' + body: + type: expression + expr: + type: op + operation: += + arguments: + - type: access + index: '{ S_11[] -> a_1[] }' + reference: __pet_ref_12 + read: 1 + write: 1 + - type: int + value: 1 +- line: -1 + domain: '{ S_10[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_10[] -> a_1[] }' + index: '{ S_10[] -> a_1[] }' + reference: __pet_ref_13 + kill: 1 +- line: -1 + domain: '{ S_3[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '{ S_3[] -> __pet_ret_0[] }' + index: '{ S_3[] -> __pet_ret_0[] }' + reference: __pet_ref_14 + kill: 1 -- 2.11.4.GIT