From 892c4f37f70d14cec21c1d95eb80b1f770c9b260 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Tue, 28 Jan 2014 11:16:24 +0100 Subject: [PATCH] add encapsulate_dynamic_control option With this option turned on, any dynamic control is encapsulated in a macro statement. We currently detect the dynamic control on our way back up the pet_tree. This means that we first create scops that may contain dynamic control and then discard and replace them with a single statement scop. This process could be optimized by detecting some dynamic control beforehand. Signed-off-by: Sven Verdoolaege --- include/pet.h | 8 ++ options.c | 8 ++ options.h | 6 ++ pet_test.sh.in | 6 ++ tests/encapsulate/dynamic_condition.c | 16 ++++ tests/encapsulate/dynamic_condition.scop | 83 ++++++++++++++++++ tests/encapsulate/for_while.c | 19 +++++ tests/encapsulate/for_while.scop | 136 +++++++++++++++++++++++++++++ tests/encapsulate/loop7.c | 13 +++ tests/encapsulate/loop7.scop | 80 ++++++++++++++++++ tests/encapsulate/while.c | 19 +++++ tests/encapsulate/while.scop | 87 +++++++++++++++++++ tests/encapsulate/while_affine.c | 14 +++ tests/encapsulate/while_affine.scop | 52 ++++++++++++ tree2scop.c | 141 +++++++++++++++++++++++++++++-- 15 files changed, 682 insertions(+), 6 deletions(-) create mode 100644 tests/encapsulate/dynamic_condition.c create mode 100644 tests/encapsulate/dynamic_condition.scop create mode 100644 tests/encapsulate/for_while.c create mode 100644 tests/encapsulate/for_while.scop create mode 100644 tests/encapsulate/loop7.c create mode 100644 tests/encapsulate/loop7.scop create mode 100644 tests/encapsulate/while.c create mode 100644 tests/encapsulate/while.scop create mode 100644 tests/encapsulate/while_affine.c create mode 100644 tests/encapsulate/while_affine.scop diff --git a/include/pet.h b/include/pet.h index 5864de1..c0aef36 100644 --- a/include/pet.h +++ b/include/pet.h @@ -27,6 +27,14 @@ int pet_options_get_autodetect(isl_ctx *ctx); int pet_options_set_detect_conditional_assignment(isl_ctx *ctx, int val); int pet_options_get_detect_conditional_assignment(isl_ctx *ctx); +/* If encapsulate-dynamic-control is set, then any dynamic control + * in the input program will be encapsulated in macro statements. + * This means in particular that no statements with arguments + * will be created. + */ +int pet_options_set_encapsulate_dynamic_control(isl_ctx *ctx, int val); +int pet_options_get_encapsulate_dynamic_control(isl_ctx *ctx); + #define PET_OVERFLOW_AVOID 0 #define PET_OVERFLOW_IGNORE 1 int pet_options_set_signed_overflow(isl_ctx *ctx, int val); diff --git a/options.c b/options.c index 0028606..e0f3285 100644 --- a/options.c +++ b/options.c @@ -46,6 +46,9 @@ ISL_ARGS_START(struct pet_options, pet_options_args) ISL_ARG_BOOL(struct pet_options, autodetect, 0, "autodetect", 0, NULL) ISL_ARG_BOOL(struct pet_options, detect_conditional_assignment, 0, "detect-conditional-assignment", 1, NULL) +ISL_ARG_BOOL(struct pet_options, encapsulate_dynamic_control, + 0, "encapsulate-dynamic-control", 0, + "encapsulate all dynamic control in macro statements") ISL_ARG_CHOICE(struct pet_options, signed_overflow, 0, "signed-overflow", pet_signed_overflow, PET_OVERFLOW_AVOID, "how to handle signed overflows") @@ -69,6 +72,11 @@ ISL_CTX_SET_BOOL_DEF(pet_options, struct pet_options, pet_options_args, ISL_CTX_GET_BOOL_DEF(pet_options, struct pet_options, pet_options_args, detect_conditional_assignment) +ISL_CTX_SET_BOOL_DEF(pet_options, struct pet_options, pet_options_args, + encapsulate_dynamic_control) +ISL_CTX_GET_BOOL_DEF(pet_options, struct pet_options, pet_options_args, + encapsulate_dynamic_control) + ISL_CTX_SET_CHOICE_DEF(pet_options, struct pet_options, pet_options_args, signed_overflow) ISL_CTX_GET_CHOICE_DEF(pet_options, struct pet_options, pet_options_args, diff --git a/options.h b/options.h index bad0be6..74dc04f 100644 --- a/options.h +++ b/options.h @@ -11,6 +11,12 @@ struct pet_options { */ int autodetect; int detect_conditional_assignment; + /* If encapsulate_dynamic_control is set, then any dynamic control + * in the input program will be encapsulated in macro statements. + * This means in particular that no statements with arguments + * will be created. + */ + int encapsulate_dynamic_control; int n_path; const char **paths; int n_define; diff --git a/pet_test.sh.in b/pet_test.sh.in index e136216..4d93ca3 100644 --- a/pet_test.sh.in +++ b/pet_test.sh.in @@ -14,3 +14,9 @@ for i in $srcdir/tests/autodetect/*.c; do (./pet$EXEEXT --autodetect $i > test.scop && ./pet_scop_cmp$EXEEXT test.scop ${i%.c}.scop) || exit done + +for i in $srcdir/tests/encapsulate/*.c; do + echo $i; + (./pet$EXEEXT --encapsulate-dynamic-control $i > test.scop && + ./pet_scop_cmp$EXEEXT test.scop ${i%.c}.scop) || exit +done diff --git a/tests/encapsulate/dynamic_condition.c b/tests/encapsulate/dynamic_condition.c new file mode 100644 index 0000000..ca8e5b2 --- /dev/null +++ b/tests/encapsulate/dynamic_condition.c @@ -0,0 +1,16 @@ +int f(void); + +void foo() +{ + int i, j, a[100]; + +#pragma scop + for (i = 0; i < 100; ++i) { + j = f(); + if (j <= 1) { + if (j >= 0) + a[i] = i; + } + } +#pragma endscop +} diff --git a/tests/encapsulate/dynamic_condition.scop b/tests/encapsulate/dynamic_condition.scop new file mode 100644 index 0000000..a89e36c --- /dev/null +++ b/tests/encapsulate/dynamic_condition.scop @@ -0,0 +1,83 @@ +start: 50 +end: 174 +indent: ' ' +context: '{ : }' +arrays: +- context: '{ : }' + extent: '{ a[i0] : i0 >= 0 and i0 <= 99 }' + element_type: int + element_size: 4 +- context: '{ : }' + extent: '{ j[] }' + element_type: int + element_size: 4 +statements: +- line: 9 + domain: '{ S_0[i] : i >= 0 and i <= 99 }' + schedule: '{ S_0[i] -> [0, i, 0] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '{ S_0[i] -> j[] }' + index: '{ S_0[i] -> j[] }' + reference: __pet_ref_0 + read: 0 + write: 1 + - type: call + name: f +- line: 10 + domain: '{ S_3[i] : i >= 0 and i <= 99 }' + schedule: '{ S_3[i] -> [0, i, 1] }' + body: + type: if + condition: + type: op + operation: <= + arguments: + - type: access + relation: '{ S_3[i] -> j[] }' + index: '{ S_3[i] -> j[] }' + reference: __pet_ref_1 + read: 1 + write: 0 + - type: int + value: 1 + then: + type: block + block: 1 + children: + - type: if + condition: + type: op + operation: '>=' + arguments: + - type: access + relation: '{ S_3[i] -> j[] }' + index: '{ S_3[i] -> j[] }' + reference: __pet_ref_2 + read: 1 + write: 0 + - type: int + value: 0 + then: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '{ S_3[i] -> a[i] }' + index: '{ S_3[i] -> a[(i)] }' + reference: __pet_ref_3 + read: 0 + write: 1 + - type: access + relation: '{ S_3[i] -> [i] }' + index: '{ S_3[i] -> [(i)] }' + reference: __pet_ref_4 + read: 1 + write: 0 diff --git a/tests/encapsulate/for_while.c b/tests/encapsulate/for_while.c new file mode 100644 index 0000000..ca401f3 --- /dev/null +++ b/tests/encapsulate/for_while.c @@ -0,0 +1,19 @@ +int f(void); +int P(int, int); +int g(int); +void h(int); + +void foo(int n) +{ + int s; + +#pragma scop + for (int x1 = 0; x1 < n; ++x1) { +S1: s = f(); + for (int x2 = 0; P(x1, x2); ++x2) { +S2: s = g(s); + } +R: h(s); + } +#pragma endscop +} diff --git a/tests/encapsulate/for_while.scop b/tests/encapsulate/for_while.scop new file mode 100644 index 0000000..f79371e --- /dev/null +++ b/tests/encapsulate/for_while.scop @@ -0,0 +1,136 @@ +start: 83 +end: 231 +indent: "\t" +context: '[n] -> { : n <= 2147483647 and n >= -2147483648 }' +arrays: +- context: '{ : }' + extent: '[n] -> { x2[] }' + element_type: int + element_size: 4 + declared: 1 +- context: '{ : }' + extent: '[n] -> { s[] }' + element_type: int + element_size: 4 +statements: +- line: 12 + domain: '[n] -> { S1[x1] : x1 <= -1 + n and x1 >= 0 }' + schedule: '[n] -> { S1[x1] -> [0, x1, 0] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '[n] -> { S1[x1] -> s[] }' + index: '[n] -> { S1[x1] -> s[] }' + reference: __pet_ref_0 + read: 0 + write: 1 + - type: call + name: f +- line: 13 + domain: '[n] -> { S_4[x1] : x1 <= -1 + n and x1 >= 0 }' + schedule: '[n] -> { S_4[x1] -> [0, x1, 1, 0] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + relation: '[n] -> { S_4[x1] -> x2[] }' + index: '[n] -> { S_4[x1] -> x2[] }' + reference: __pet_ref_1 + read: 0 + write: 0 +- line: 13 + domain: '[n] -> { S_3[x1] : x1 <= -1 + n and x1 >= 0 }' + schedule: '[n] -> { S_3[x1] -> [0, x1, 1, 1] }' + body: + type: for + declared: 1 + variable: + type: access + relation: '[n] -> { S_3[x1] -> x2[] }' + index: '[n] -> { S_3[x1] -> x2[] }' + reference: __pet_ref_2 + read: 0 + write: 1 + initialization: + type: int + value: 0 + condition: + type: call + name: P + arguments: + - type: access + relation: '[n] -> { S_3[x1] -> [x1] }' + index: '[n] -> { S_3[x1] -> [(x1)] }' + reference: __pet_ref_3 + read: 1 + write: 0 + - type: access + relation: '[n] -> { S_3[x1] -> x2[] }' + index: '[n] -> { S_3[x1] -> x2[] }' + reference: __pet_ref_4 + read: 1 + write: 0 + increment: + type: int + value: 1 + body: + type: block + block: 1 + children: + - type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '[n] -> { S_3[x1] -> s[] }' + index: '[n] -> { S_3[x1] -> s[] }' + reference: __pet_ref_5 + read: 0 + write: 1 + - type: call + name: g + arguments: + - type: access + relation: '[n] -> { S_3[x1] -> s[] }' + index: '[n] -> { S_3[x1] -> s[] }' + reference: __pet_ref_6 + read: 1 + write: 0 +- line: 13 + domain: '[n] -> { S_5[x1] : x1 <= -1 + n and x1 >= 0 }' + schedule: '[n] -> { S_5[x1] -> [0, x1, 1, 2] }' + body: + type: expression + expr: + type: op + operation: kill + arguments: + - type: access + relation: '[n] -> { S_5[x1] -> x2[] }' + index: '[n] -> { S_5[x1] -> x2[] }' + reference: __pet_ref_7 + read: 0 + write: 0 +- line: 16 + domain: '[n] -> { R[x1] : x1 <= -1 + n and x1 >= 0 }' + schedule: '[n] -> { R[x1] -> [0, x1, 2] }' + body: + type: expression + expr: + type: call + name: h + arguments: + - type: access + relation: '[n] -> { R[x1] -> s[] }' + index: '[n] -> { R[x1] -> s[] }' + reference: __pet_ref_8 + read: 1 + write: 0 diff --git a/tests/encapsulate/loop7.c b/tests/encapsulate/loop7.c new file mode 100644 index 0000000..32d641b --- /dev/null +++ b/tests/encapsulate/loop7.c @@ -0,0 +1,13 @@ +int f(); + +void foo() +{ + int i; + int a; + +#pragma scop + i = f(); + for (i = i; i < 10; ++i) + a = 5; +#pragma endscop +} diff --git a/tests/encapsulate/loop7.scop b/tests/encapsulate/loop7.scop new file mode 100644 index 0000000..9e1671e --- /dev/null +++ b/tests/encapsulate/loop7.scop @@ -0,0 +1,80 @@ +start: 40 +end: 114 +indent: "\t" +context: '{ : }' +arrays: +- context: '{ : }' + extent: '{ a[] }' + element_type: int + element_size: 4 +- context: '{ : }' + extent: '{ i[] }' + element_type: int + element_size: 4 +statements: +- line: 9 + domain: '{ S_0[] }' + schedule: '{ S_0[] -> [0] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '{ S_0[] -> i[] }' + index: '{ S_0[] -> i[] }' + reference: __pet_ref_0 + read: 0 + write: 1 + - type: call + name: f +- line: 10 + domain: '{ S_5[] }' + schedule: '{ S_5[] -> [1] }' + body: + type: for + declared: 0 + variable: + type: access + relation: '{ S_5[] -> i[] }' + index: '{ S_5[] -> i[] }' + reference: __pet_ref_1 + read: 0 + write: 1 + initialization: + type: access + relation: '{ S_5[] -> i[] }' + index: '{ S_5[] -> i[] }' + reference: __pet_ref_2 + read: 1 + write: 0 + condition: + type: op + operation: < + arguments: + - type: access + relation: '{ S_5[] -> i[] }' + index: '{ S_5[] -> i[] }' + reference: __pet_ref_3 + read: 1 + write: 0 + - type: int + value: 10 + increment: + type: int + value: 1 + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '{ S_5[] -> a[] }' + index: '{ S_5[] -> a[] }' + reference: __pet_ref_4 + read: 0 + write: 1 + - type: int + value: 5 diff --git a/tests/encapsulate/while.c b/tests/encapsulate/while.c new file mode 100644 index 0000000..1508d65 --- /dev/null +++ b/tests/encapsulate/while.c @@ -0,0 +1,19 @@ +int f(void); +int P(int, int); +int g(int); +void h(int); + +void foo(int n) +{ + int s; + +#pragma scop + for (int x = 0; x < n; ++x) { +S1: s = f(); + while (P(x, s)) { +S2: s = g(s); + } +R: h(s); + } +#pragma endscop +} diff --git a/tests/encapsulate/while.scop b/tests/encapsulate/while.scop new file mode 100644 index 0000000..2ae9654 --- /dev/null +++ b/tests/encapsulate/while.scop @@ -0,0 +1,87 @@ +start: 83 +end: 210 +indent: "\t" +context: '[n] -> { : n <= 2147483647 and n >= -2147483648 }' +arrays: +- context: '{ : }' + extent: '[n] -> { s[] }' + element_type: int + element_size: 4 +statements: +- line: 12 + domain: '[n] -> { S1[x] : x <= -1 + n and x >= 0 }' + schedule: '[n] -> { S1[x] -> [0, x, 0] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '[n] -> { S1[x] -> s[] }' + index: '[n] -> { S1[x] -> s[] }' + reference: __pet_ref_0 + read: 0 + write: 1 + - type: call + name: f +- line: 13 + domain: '[n] -> { S_3[x] : x <= -1 + n and x >= 0 }' + schedule: '[n] -> { S_3[x] -> [0, x, 1] }' + body: + type: while + condition: + type: call + name: P + arguments: + - type: access + relation: '[n] -> { S_3[x] -> [x] }' + index: '[n] -> { S_3[x] -> [(x)] }' + reference: __pet_ref_1 + read: 1 + write: 0 + - type: access + relation: '[n] -> { S_3[x] -> s[] }' + index: '[n] -> { S_3[x] -> s[] }' + reference: __pet_ref_2 + read: 1 + write: 0 + body: + type: block + block: 1 + children: + - type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '[n] -> { S_3[x] -> s[] }' + index: '[n] -> { S_3[x] -> s[] }' + reference: __pet_ref_3 + read: 0 + write: 1 + - type: call + name: g + arguments: + - type: access + relation: '[n] -> { S_3[x] -> s[] }' + index: '[n] -> { S_3[x] -> s[] }' + reference: __pet_ref_4 + read: 1 + write: 0 +- line: 16 + domain: '[n] -> { R[x] : x <= -1 + n and x >= 0 }' + schedule: '[n] -> { R[x] -> [0, x, 2] }' + body: + type: expression + expr: + type: call + name: h + arguments: + - type: access + relation: '[n] -> { R[x] -> s[] }' + index: '[n] -> { R[x] -> s[] }' + reference: __pet_ref_5 + read: 1 + write: 0 diff --git a/tests/encapsulate/while_affine.c b/tests/encapsulate/while_affine.c new file mode 100644 index 0000000..cfc177b --- /dev/null +++ b/tests/encapsulate/while_affine.c @@ -0,0 +1,14 @@ +void foo(int N) +{ + int i, j, a[N], b[N]; + +#pragma scop + for (i = 0; i < 100; ++i) + while (i > 98) { + for (j = 0; j < N; ++j) + a[j] = 0; + for (j = 0; j < N; ++j) + b[j] = a[j]; + } +#pragma endscop +} diff --git a/tests/encapsulate/while_affine.scop b/tests/encapsulate/while_affine.scop new file mode 100644 index 0000000..924b38e --- /dev/null +++ b/tests/encapsulate/while_affine.scop @@ -0,0 +1,52 @@ +start: 42 +end: 206 +indent: "\t" +context: '[N] -> { : N >= 0 and N <= 2147483647 }' +arrays: +- context: '[N] -> { : N >= 0 }' + extent: '[N] -> { a[i0] : i0 <= -1 + N and i0 >= 0 }' + element_type: int + element_size: 4 +- context: '[N] -> { : N >= 0 }' + extent: '[N] -> { b[i0] : i0 <= -1 + N and i0 >= 0 }' + element_type: int + element_size: 4 +statements: +- line: 9 + domain: '[N] -> { S_0[99, t, j] : j >= 0 and t >= 0 and j <= -1 + N }' + schedule: '[N] -> { S_0[i, t, j] -> [0, i, t, 0, j] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '[N] -> { S_0[i, t, j] -> a[j] }' + index: '[N] -> { S_0[i, t, j] -> a[(j)] }' + reference: __pet_ref_0 + read: 0 + write: 1 + - type: int + value: 0 +- line: 11 + domain: '[N] -> { S_1[99, t, j] : j >= 0 and t >= 0 and j <= -1 + N }' + schedule: '[N] -> { S_1[i, t, j] -> [0, i, t, 1, j] }' + body: + type: expression + expr: + type: op + operation: = + arguments: + - type: access + relation: '[N] -> { S_1[i, t, j] -> b[j] }' + index: '[N] -> { S_1[i, t, j] -> b[(j)] }' + reference: __pet_ref_1 + read: 0 + write: 1 + - type: access + relation: '[N] -> { S_1[i, t, j] -> a[j] }' + index: '[N] -> { S_1[i, t, j] -> a[(j)] }' + reference: __pet_ref_2 + read: 1 + write: 0 diff --git a/tree2scop.c b/tree2scop.c index 689c1c5..435f8ab 100644 --- a/tree2scop.c +++ b/tree2scop.c @@ -2073,16 +2073,133 @@ static struct pet_scop *scop_from_block(__isl_keep pet_tree *tree, return scop; } +/* Internal data structure for extract_declared_arrays. + * + * "pc" and "state" are used to create pet_array objects and kill statements. + * "any" is initialized to 0 by the caller and set to 1 as soon as we have + * found any declared array. + * "scop" has been initialized by the caller and is used to attach + * the created pet_array objects. + * "kill_before" and "kill_after" are created and updated by + * extract_declared_arrays to collect the kills of the arrays. + */ +struct pet_tree_extract_declared_arrays_data { + pet_context *pc; + struct pet_state *state; + + isl_ctx *ctx; + + int any; + struct pet_scop *scop; + struct pet_scop *kill_before; + struct pet_scop *kill_after; +}; + +/* Check if the node "node" declares any array or scalar. + * If so, create the corresponding pet_array and attach it to data->scop. + * Additionally, create two kill statements for the array and add them + * to data->kill_before and data->kill_after. + */ +static int extract_declared_arrays(__isl_keep pet_tree *node, void *user) +{ + enum pet_tree_type type; + struct pet_tree_extract_declared_arrays_data *data = user; + struct pet_array *array; + struct pet_scop *scop_kill; + pet_expr *var; + + type = pet_tree_get_type(node); + if (type == pet_tree_decl || type == pet_tree_decl_init) + var = node->u.d.var; + else if (type == pet_tree_for && node->u.l.declared) + var = node->u.l.iv; + else + return 0; + + array = extract_array(var, data->pc, data->state); + if (array) + array->declared = 1; + data->scop = pet_scop_add_array(data->scop, array); + + scop_kill = kill(pet_tree_get_loc(node), array, data->pc, data->state); + if (!data->any) + data->kill_before = scop_kill; + else + data->kill_before = pet_scop_add_par(data->ctx, + data->kill_before, scop_kill); + + scop_kill = kill(pet_tree_get_loc(node), array, data->pc, data->state); + if (!data->any) + data->kill_after = scop_kill; + else + data->kill_after = pet_scop_add_par(data->ctx, + data->kill_after, scop_kill); + + data->any = 1; + + return 0; +} + +/* Convert a pet_tree that consists of more than a single leaf + * to a pet_scop with a single statement encapsulating the entire pet_tree. + * Do so within the context of "pc". + * + * After constructing the core scop, we also look for any arrays (or scalars) + * that are declared inside "tree". Each of those arrays is marked as + * having been declared and kill statements for these arrays + * are introduced before and after the core scop. + * Note that the input tree is not a leaf so that the declaration + * cannot occur at the outer level. + */ +static struct pet_scop *scop_from_tree_macro(__isl_take pet_tree *tree, + __isl_take isl_id *label, __isl_keep pet_context *pc, + struct pet_state *state) +{ + struct pet_tree_extract_declared_arrays_data data = { pc, state }; + + data.scop = scop_from_unevaluated_tree(pet_tree_copy(tree), + state->n_stmt++, pc); + + data.any = 0; + data.ctx = pet_context_get_ctx(pc); + if (pet_tree_foreach_sub_tree(tree, &extract_declared_arrays, + &data) < 0) + data.scop = pet_scop_free(data.scop); + pet_tree_free(tree); + + if (!data.any) + return data.scop; + + data.kill_before = pet_scop_prefix(data.kill_before, 0); + data.scop = pet_scop_prefix(data.scop, 1); + data.kill_after = pet_scop_prefix(data.kill_after, 2); + + data.scop = pet_scop_add_seq(data.ctx, data.kill_before, data.scop); + data.scop = pet_scop_add_seq(data.ctx, data.scop, data.kill_after); + + return data.scop; +} + /* Construct a pet_scop that corresponds to the pet_tree "tree" * within the context "pc" by calling the appropriate function * based on the type of "tree". + * + * If the initially constructed pet_scop turns out to involve + * dynamic control and if the user has requested an encapsulation + * of all dynamic control, then this pet_scop is discarded and + * a new pet_scop is created with a single statement representing + * the entire "tree". */ static struct pet_scop *scop_from_tree(__isl_keep pet_tree *tree, __isl_keep pet_context *pc, struct pet_state *state) { + isl_ctx *ctx; + struct pet_scop *scop = NULL; + if (!tree) return NULL; + ctx = pet_tree_get_ctx(tree); switch (tree->type) { case pet_tree_error: return NULL; @@ -2100,17 +2217,29 @@ static struct pet_scop *scop_from_tree(__isl_keep pet_tree *tree, state->n_stmt++, pc); case pet_tree_if: case pet_tree_if_else: - return scop_from_if(tree, pc, state); + scop = scop_from_if(tree, pc, state); + break; case pet_tree_for: - return scop_from_for(tree, pc, state); + scop = scop_from_for(tree, pc, state); + break; case pet_tree_while: - return scop_from_while(tree, pc, state); + scop = scop_from_while(tree, pc, state); + break; case pet_tree_infinite_loop: - return scop_from_infinite_for(tree, pc, state); + scop = scop_from_infinite_for(tree, pc, state); + break; } - isl_die(tree->ctx, isl_error_internal, "unhandled type", - return NULL); + if (!scop) + return NULL; + + if (!pet_options_get_encapsulate_dynamic_control(ctx) || + !pet_scop_has_data_dependent_conditions(scop)) + return scop; + + pet_scop_free(scop); + return scop_from_tree_macro(pet_tree_copy(tree), + isl_id_copy(tree->label), pc, state); } /* Construct a pet_scop that corresponds to the pet_tree "tree". -- 2.11.4.GIT