From 56470feb630f08db797130be65b5a985a4c07a06 Mon Sep 17 00:00:00 2001 From: Oleksandr Zinenko Date: Thu, 16 Apr 2015 16:06:30 +0200 Subject: [PATCH] osl_scop_remove_unions functionality --- include/osl/scop.h.in | 1 + include/osl/statement.h | 1 + source/scop.c | 47 ++++++++++++++++++++++++++++++++++++++++++ source/statement.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/osl_test.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 152 insertions(+), 1 deletion(-) diff --git a/include/osl/scop.h.in b/include/osl/scop.h.in index 5b429c0..539a4d3 100644 --- a/include/osl/scop.h.in +++ b/include/osl/scop.h.in @@ -141,6 +141,7 @@ void osl_scop_free(osl_scop_p); void osl_scop_add(osl_scop_p *, osl_scop_p); size_t osl_scop_number(osl_scop_p); osl_scop_p osl_scop_clone(osl_scop_p); +osl_scop_p osl_scop_remove_unions(osl_scop_p); int osl_scop_equal(osl_scop_p, osl_scop_p); int osl_scop_integrity_check(osl_scop_p); int osl_scop_check_compatible_scoplib(osl_scop_p); diff --git a/include/osl/statement.h b/include/osl/statement.h index fb1937a..9bc04f5 100644 --- a/include/osl/statement.h +++ b/include/osl/statement.h @@ -132,6 +132,7 @@ void osl_statement_compact(osl_statement_p, int); int osl_statement_number(osl_statement_p); osl_statement_p osl_statement_nclone(osl_statement_p, int); osl_statement_p osl_statement_clone(osl_statement_p); +osl_statement_p osl_statement_remove_unions(osl_statement_p); int osl_statement_equal(osl_statement_p, osl_statement_p); int osl_statement_integrity_check(osl_statement_p, int); int osl_statement_get_nb_iterators(osl_statement_p); diff --git a/source/scop.c b/source/scop.c index 1e5c046..0c20ab4 100644 --- a/source/scop.c +++ b/source/scop.c @@ -663,6 +663,53 @@ osl_scop_p osl_scop_clone(osl_scop_p scop) { return clone; } +/** + * osl_scop_remove_unions function: + * Replace each statement having unions of relations by a list of statements, + * each of which has exactly one domain relation and one scattering relation. + * \param[in] scop A SCoP with statements featuring unions of relations. + * \returns An identical SCoP without unions of relations. + */ +osl_scop_p osl_scop_remove_unions(osl_scop_p scop) { + osl_statement_p statement, new_statement, scop_statement_ptr; + osl_scop_p new_scop, scop_ptr, result = NULL; + + for ( ; scop != NULL; scop = scop->next) { + statement = scop->statement; + scop_statement_ptr = NULL; + new_scop = osl_scop_malloc(); + + for ( ; statement != NULL; statement = statement->next) { + new_statement = osl_statement_remove_unions(statement); + if (!scop_statement_ptr) { + scop_statement_ptr = new_statement; + new_scop->statement = scop_statement_ptr; + } else { + scop_statement_ptr->next = new_statement; + scop_statement_ptr = scop_statement_ptr->next; + } + } + + new_scop->context = osl_relation_clone(scop->context); + new_scop->extension = osl_generic_clone(scop->extension); + if (scop->language != NULL) { + new_scop->language = (char *) malloc(strlen(scop->language) + 1); + new_scop->language = strcpy(new_scop->language, scop->language); + } + new_scop->parameters = osl_generic_clone(scop->parameters); + new_scop->registry = osl_interface_clone(scop->registry); + new_scop->version = scop->version; + if (!result) { + result = new_scop; + scop_ptr = new_scop; + } else { + scop_ptr->next = new_scop; + scop_ptr = scop_ptr->next; + } + } + + return result; +} /** * osl_scop_equal function: diff --git a/source/statement.c b/source/statement.c index 486f995..a15f5bc 100644 --- a/source/statement.c +++ b/source/statement.c @@ -629,6 +629,61 @@ osl_statement_p osl_statement_clone(osl_statement_p statement) { return osl_statement_nclone(statement, -1); } +/// Clone first part of the union, return NULL if input is NULL. +static osl_relation_p osl_relation_clone_one_safe(osl_relation_p relation) { + if (relation == NULL) + return NULL; + return osl_relation_nclone(relation, 1); +} + +/** + * osl_statement_remove_unions function: + * Create a statement list from a statement containing unions of relations in + * domain and/or scattering. This functions constructs multiple new statements + * and keeps the original statement intact. Each new statement has exactly one + * domain union component and exactly one scattering union component. If the + * statement does not have the domain relation or the scattering relation, this + * function returns \c NULL. + * \param[in] statement A pointer to the statement + * \return A pointer to the head of the newly created statement list. + */ +osl_statement_p osl_statement_remove_unions(osl_statement_p statement) { + osl_relation_p domain, scattering; + osl_statement_p statement_ptr, result; + if (!statement) + return NULL; + + // Make at least one new statement, even if there are no relations. + domain = statement->domain; + scattering = statement->scattering; + result = NULL; + do { + do { + osl_statement_p new_statement = osl_statement_malloc(); + new_statement->domain = osl_relation_clone_one_safe(domain); + new_statement->scattering = osl_relation_clone_one_safe(scattering); + new_statement->access = osl_relation_list_clone(statement->access); + new_statement->extension = osl_generic_clone(statement->extension); + if (!result) { + statement_ptr = new_statement; + result = new_statement; + } else { + statement_ptr->next = new_statement; + statement_ptr = statement_ptr->next; + } + if (scattering == NULL || scattering->next == NULL) + break; + scattering = scattering->next; + } while (1); + if (domain == NULL || domain->next == NULL) + break; + domain = domain->next; + } while (1); + + return result; +} + + /** * osl_statement_equal function: diff --git a/tests/osl_test.c b/tests/osl_test.c index 26d27c8..8f7ef48 100644 --- a/tests/osl_test.c +++ b/tests/osl_test.c @@ -76,6 +76,49 @@ #define TEST_DIR "." // Directory to scan for OpenScop files #define TEST_SUFFIX ".scop" // Suffix of OpenScop files +/// Check if a scop without unions corresponds to the one with unions. +static int test_unions(osl_scop_p scop) { + osl_statement_p stmt, nounion_stmt; + osl_scop_p nounion_scop = osl_scop_remove_unions(scop); + osl_relation_p domain, scattering; + int result = 1; + osl_scop_print(stderr, nounion_scop); + for ( ; scop != NULL && nounion_scop != NULL; scop = scop->next, nounion_scop = nounion_scop->next) { + nounion_stmt = nounion_scop->statement; + for (stmt = scop->statement; stmt != NULL; stmt = stmt->next) { + domain = stmt->domain; + scattering = stmt->scattering; + do { + do { + if (nounion_stmt == NULL) + return 0; + result = result && osl_relation_part_equal(domain, nounion_stmt->domain); + result = result && osl_relation_part_equal(scattering, nounion_stmt->scattering); + result = result && (nounion_stmt->domain == NULL || nounion_stmt->domain->next == NULL); + result = result && (nounion_stmt->scattering == NULL || nounion_stmt->scattering->next == NULL); + result = result && osl_relation_list_equal(nounion_stmt->access, stmt->access); + result = result && osl_generic_equal(nounion_stmt->extension, stmt->extension); + if (result == 0) + return 0; + nounion_stmt = nounion_stmt->next; + + if (scattering == NULL || scattering->next == NULL) + break; + scattering = scattering->next; + } while (1); + if (domain == NULL || domain->next == NULL) + break; + domain = domain->next; + } while (1); + } + if (nounion_stmt != NULL) + return 0; + } + if (scop != NULL || nounion_scop != NULL) + return 0; + osl_scop_free(nounion_scop); + return 1; +} /** * test_file function @@ -95,6 +138,7 @@ int test_file(char* input_name, int verbose) { int cloning = 0; int dumping = 0; int equal = 0; + int unions = 0; FILE* input_file; FILE* output_file; osl_scop_p input_scop; @@ -151,8 +195,11 @@ int test_file(char* input_name, int verbose) { else printf("- dumping failed\n"); + // PART V. Remove unions. + unions = test_unions(input_scop); + // PART IV. Report. - if ((equal = (cloning + dumping > 1) ? 1 : 0)) + if ((equal = (cloning + dumping + unions > 2) ? 1 : 0)) printf("Success :-)\n"); else printf("Failure :-(\n"); -- 2.11.4.GIT