From 5d1004252648acb81014b34b2eb77c47a87bfe75 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 15 Apr 2016 12:09:46 +0200 Subject: [PATCH] perform substitutions on size expression of array declared in inlined function During inlining, the function parameters may get renamed apart from other variables in the calling function. These renamings are applied to the tree representing the body of the inlined function, but the size expressions of the arrays declared in the function are only derived afterwards and these substitutions are therefore not taken into account in the size expressions. Precompute these size expressions and replace them by the result of applying the substitutions such that later calls to get_array_size will return the modified size expressions. Reported-by: Bruno bodin Signed-off-by: Sven Verdoolaege --- scan.cc | 59 ++++++++++++++++++++++ scan.h | 2 + tests/inline11.c | 16 ++++++ tests/inline11.scop | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 218 insertions(+) create mode 100644 tests/inline11.c create mode 100644 tests/inline11.scop diff --git a/scan.cc b/scan.cc index 9a62019..72ee0c5 100644 --- a/scan.cc +++ b/scan.cc @@ -1863,6 +1863,59 @@ int PetScan::set_inliner_arguments(pet_inliner &inliner, CallExpr *call, return 0; } +/* Internal data structure for PetScan::substitute_array_sizes. + * ps is the PetScan on which the method was called. + * substituter is the substituter that is used to substitute variables + * in the size expressions. + */ +struct pet_substitute_array_sizes_data { + PetScan *ps; + pet_substituter *substituter; +}; + +extern "C" { + static int substitute_array_size(__isl_keep pet_tree *tree, void *user); +} + +/* If "tree" is a declaration, then perform the substitutions + * in data->substituter on its size expression and store the result + * in the size expression cache of data->ps such that the modified expression + * will be used in subsequent calls to get_array_size. + */ +static int substitute_array_size(__isl_keep pet_tree *tree, void *user) +{ + struct pet_substitute_array_sizes_data *data; + isl_id *id; + pet_expr *var, *size; + + if (!pet_tree_is_decl(tree)) + return 0; + + data = (struct pet_substitute_array_sizes_data *) user; + var = pet_tree_decl_get_var(tree); + id = pet_expr_access_get_id(var); + pet_expr_free(var); + + size = data->ps->get_array_size(id); + size = data->substituter->substitute(size); + data->ps->set_array_size(id, size); + + return 0; +} + +/* Perform the substitutions in "substituter" on all the arrays declared + * inside "tree" and store the results in the size expression cache + * such that the modified expressions will be used in subsequent calls + * to get_array_size. + */ +int PetScan::substitute_array_sizes(__isl_keep pet_tree *tree, + pet_substituter *substituter) +{ + struct pet_substitute_array_sizes_data data = { this, substituter }; + + return pet_tree_foreach_sub_tree(tree, &substitute_array_size, &data); +} + /* Try and construct a pet_tree from the body of "fd" using the actual * arguments in "call" in place of the formal arguments. * "fd" is assumed to point to the declaration with a function body. @@ -1876,6 +1929,10 @@ int PetScan::set_inliner_arguments(pet_inliner &inliner, CallExpr *call, * 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 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 + * itself, but rather in the size expression cache. * * During the extraction of the function body, all variables names * that are declared in the calling function as well all variable @@ -1913,6 +1970,8 @@ __isl_give pet_tree *PetScan::extract_inlined_call(CallExpr *call, tree_loc = construct_pet_loc(call->getSourceRange(), true); tree = pet_tree_set_loc(tree, tree_loc); + substitute_array_sizes(tree, &inliner); + return inliner.inline_tree(tree); } diff --git a/scan.h b/scan.h index bb91b60..b10f2b5 100644 --- a/scan.h +++ b/scan.h @@ -192,6 +192,8 @@ private: clang::QualType qt, int pos); struct pet_array *set_upper_bounds(struct pet_array *array, __isl_keep pet_context *pc); + int substitute_array_sizes(__isl_keep pet_tree *tree, + pet_substituter *substituter); __isl_give pet_tree *insert_initial_declarations( __isl_take pet_tree *tree, int n_decl, diff --git a/tests/inline11.c b/tests/inline11.c new file mode 100644 index 0000000..94a64bd --- /dev/null +++ b/tests/inline11.c @@ -0,0 +1,16 @@ +inline void f1(int n) +{ +} + +inline void f2(int n) +{ + float A[n]; +} + +void f(int s) +{ +#pragma scop + f1(s); + f2(s); +#pragma endscop +} diff --git a/tests/inline11.scop b/tests/inline11.scop new file mode 100644 index 0000000..1b09af1 --- /dev/null +++ b/tests/inline11.scop @@ -0,0 +1,141 @@ +start: 83 +end: 128 +indent: "\t" +context: '[s] -> { : 0 <= s <= 2147483647 }' +schedule: '{ domain: "[s] -> { S_3[]; S_5[]; S_6[]; S_0[]; S_2[]; S_7[]; S_4[]; S_1[] + }", child: { sequence: [ { filter: "{ S_0[] }" }, { filter: "{ S_1[] }" }, { filter: + "{ S_2[] }" }, { filter: "{ S_3[] }" }, { filter: "{ S_4[] }" }, { filter: "{ S_6[] + }" }, { filter: "{ S_7[] }" }, { filter: "{ S_5[] }" } ] } }' +arrays: +- context: '{ : }' + extent: '[s] -> { n[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[s] -> { n_0[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '[s] -> { : s >= 0 }' + extent: '[s] -> { A[i0] : 0 <= i0 < s }' + element_type: float + element_size: 4 + declared: 1 +statements: +- line: -1 + domain: '[s] -> { S_0[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[s] -> { S_0[] -> n[] }' + index: '[s] -> { S_0[] -> n[] }' + reference: __pet_ref_0 + kill: 1 +- line: -1 + domain: '[s] -> { S_1[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[s] -> { S_1[] -> n[] }' + reference: __pet_ref_1 + read: 0 + write: 1 + - type: access + index: '[s] -> { S_1[] -> [(s)] }' + reference: __pet_ref_2 + read: 1 + write: 0 +- line: -1 + domain: '[s] -> { S_2[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[s] -> { S_2[] -> n[] }' + index: '[s] -> { S_2[] -> n[] }' + reference: __pet_ref_3 + kill: 1 +- line: -1 + domain: '[s] -> { S_3[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[s] -> { S_3[] -> n_0[] }' + index: '[s] -> { S_3[] -> n_0[] }' + reference: __pet_ref_4 + kill: 1 +- line: -1 + domain: '[s] -> { S_4[] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + index: '[s] -> { S_4[] -> n_0[] }' + reference: __pet_ref_5 + read: 0 + write: 1 + - type: access + index: '[s] -> { S_4[] -> [(s)] }' + reference: __pet_ref_6 + read: 1 + write: 0 +- line: 7 + domain: '[s] -> { S_6[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[s] -> { S_6[] -> A[o0] : 0 <= o0 < s }' + index: '[s] -> { S_6[] -> A[] }' + depth: 1 + reference: __pet_ref_7 + kill: 1 +- line: 7 + domain: '[s] -> { S_7[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[s] -> { S_7[] -> A[o0] : 0 <= o0 < s }' + index: '[s] -> { S_7[] -> A[] }' + depth: 1 + reference: __pet_ref_8 + kill: 1 +- line: -1 + domain: '[s] -> { S_5[] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + killed: '[s] -> { S_5[] -> n_0[] }' + index: '[s] -> { S_5[] -> n_0[] }' + reference: __pet_ref_9 + kill: 1 -- 2.11.4.GIT