OpenScop 0.8.1
|
00001 00002 /*+-----------------------------------------------------------------** 00003 ** OpenScop Library ** 00004 **-----------------------------------------------------------------** 00005 ** statement.c ** 00006 **-----------------------------------------------------------------** 00007 ** First version: 30/04/2008 ** 00008 **-----------------------------------------------------------------** 00009 00010 00011 ***************************************************************************** 00012 * OpenScop: Structures and formats for polyhedral tools to talk together * 00013 ***************************************************************************** 00014 * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, * 00015 * / / / // // // // / / / // // / / // / /|,_, * 00016 * / / / // // // // / / / // // / / // / / / /\ * 00017 * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ * 00018 * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ * 00019 * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ * 00020 * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ * 00021 * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ * 00022 * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ * 00023 * | I | | | | e | | | | | | | | | | | | | \ \ \ * 00024 * | T | | | | | | | | | | | | | | | | | \ \ \ * 00025 * | E | | | | | | | | | | | | | | | | | \ \ \ * 00026 * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ * 00027 * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / * 00028 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' * 00029 * * 00030 * Copyright (C) 2008 University Paris-Sud 11 and INRIA * 00031 * * 00032 * (3-clause BSD license) * 00033 * Redistribution and use in source and binary forms, with or without * 00034 * modification, are permitted provided that the following conditions * 00035 * are met: * 00036 * * 00037 * 1. Redistributions of source code must retain the above copyright notice, * 00038 * this list of conditions and the following disclaimer. * 00039 * 2. Redistributions in binary form must reproduce the above copyright * 00040 * notice, this list of conditions and the following disclaimer in the * 00041 * documentation and/or other materials provided with the distribution. * 00042 * 3. The name of the author may not be used to endorse or promote products * 00043 * derived from this software without specific prior written permission. * 00044 * * 00045 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * 00046 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * 00047 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * 00048 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * 00049 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * 00050 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * 00051 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * 00052 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 00053 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * 00054 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 00055 * * 00056 * OpenScop Library, a library to manipulate OpenScop formats and data * 00057 * structures. Written by: * 00058 * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and * 00059 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> * 00060 * * 00061 *****************************************************************************/ 00062 00063 00064 #include <stdlib.h> 00065 #include <stdio.h> 00066 #include <string.h> 00067 #include <ctype.h> 00068 00069 #include <osl/macros.h> 00070 #include <osl/util.h> 00071 #include <osl/strings.h> 00072 #include <osl/body.h> 00073 #include <osl/relation.h> 00074 #include <osl/relation_list.h> 00075 #include <osl/names.h> 00076 #include <osl/interface.h> 00077 #include <osl/generic.h> 00078 #include <osl/statement.h> 00079 00080 00081 /*+*************************************************************************** 00082 * Structure display functions * 00083 *****************************************************************************/ 00084 00085 00096 void osl_statement_idump(FILE * file, osl_statement_p statement, int level) { 00097 int j, first = 1, number = 1; 00098 00099 // Go to the right level. 00100 for (j = 0; j < level; j++) 00101 fprintf(file, "|\t"); 00102 00103 if (statement != NULL) 00104 fprintf(file, "+-- osl_statement_t (S%d)\n", number); 00105 else 00106 fprintf(file, "+-- NULL statement\n"); 00107 00108 while (statement != NULL) { 00109 if (!first) { 00110 // Go to the right level. 00111 for (j = 0; j < level; j++) 00112 fprintf(file, "|\t"); 00113 fprintf(file, "| osl_statement_t (S%d)\n", number); 00114 } 00115 else 00116 first = 0; 00117 00118 // A blank line. 00119 for (j = 0; j <= level + 1; j++) 00120 fprintf(file, "|\t"); 00121 fprintf(file, "\n"); 00122 00123 // Print the domain of the statement. 00124 osl_relation_idump(file, statement->domain, level + 1); 00125 00126 // Print the scattering of the statement. 00127 osl_relation_idump(file, statement->scattering, level + 1); 00128 00129 // Print the array access information of the statement. 00130 osl_relation_list_idump(file, statement->access, level + 1); 00131 00132 // Print the original body expression. 00133 osl_generic_idump(file, statement->body, level + 1); 00134 00135 statement = statement->next; 00136 number++; 00137 00138 // Next line. 00139 if (statement != NULL) { 00140 for (j = 0; j <= level; j++) 00141 fprintf(file, "|\t"); 00142 fprintf(file, "V\n"); 00143 } 00144 } 00145 00146 // The last line. 00147 for (j = 0; j <= level; j++) 00148 fprintf(file, "|\t"); 00149 fprintf(file, "\n"); 00150 } 00151 00152 00160 void osl_statement_dump(FILE * file, osl_statement_p statement) { 00161 osl_statement_idump(file, statement, 0); 00162 } 00163 00164 00172 static 00173 osl_names_p osl_statement_names(osl_statement_p statement) { 00174 int nb_parameters = OSL_UNDEFINED; 00175 int nb_iterators = OSL_UNDEFINED; 00176 int nb_scattdims = OSL_UNDEFINED; 00177 int nb_localdims = OSL_UNDEFINED; 00178 int array_id = OSL_UNDEFINED; 00179 00180 osl_statement_get_attributes(statement, &nb_parameters, &nb_iterators, 00181 &nb_scattdims, &nb_localdims, &array_id); 00182 00183 return osl_names_generate("P", nb_parameters, 00184 "i", nb_iterators, 00185 "c", nb_scattdims, 00186 "l", nb_localdims, 00187 "A", array_id); 00188 } 00189 00190 00199 void osl_statement_pprint(FILE * file, osl_statement_p statement, 00200 osl_names_p names) { 00201 int nb_relations, number = 1; 00202 int generated_names = 0; 00203 int iterators_backedup = 0; 00204 osl_strings_p iterators_backup = NULL; 00205 00206 // Generate the dimension names if necessary and replace iterators with 00207 // statement iterators if possible. 00208 if (names == NULL) { 00209 generated_names = 1; 00210 names = osl_statement_names(statement); 00211 } 00212 00213 while (statement != NULL) { 00214 // If possible, replace iterator names with statement iterator names. 00215 if (osl_generic_has_URI(statement->body, OSL_URI_BODY) && 00216 (((osl_body_p)(statement->body->data))->iterators != NULL)) { 00217 iterators_backedup = 1; 00218 iterators_backup = names->iterators; 00219 names->iterators = ((osl_body_p)(statement->body->data))->iterators; 00220 } 00221 00222 nb_relations = 0; 00223 00224 fprintf(file, "# =============================================== "); 00225 fprintf(file, "Statement %d\n", number); 00226 00227 fprintf(file, "# Number of relations describing the statement:\n"); 00228 00229 if (statement->domain != NULL) 00230 nb_relations ++; 00231 if (statement->scattering != NULL) 00232 nb_relations ++; 00233 nb_relations += osl_relation_list_count(statement->access); 00234 00235 fprintf(file, "%d\n\n", nb_relations); 00236 00237 fprintf(file, "# ---------------------------------------------- "); 00238 fprintf(file, "%2d.1 Domain\n", number); 00239 osl_relation_pprint(file, statement->domain, names); 00240 fprintf(file, "\n"); 00241 00242 fprintf(file, "# ---------------------------------------------- "); 00243 fprintf(file, "%2d.2 Scattering\n", number); 00244 osl_relation_pprint(file, statement->scattering, names); 00245 fprintf(file, "\n"); 00246 00247 fprintf(file, "# ---------------------------------------------- "); 00248 fprintf(file, "%2d.3 Access\n", number); 00249 osl_relation_list_pprint_elts(file, statement->access, names); 00250 fprintf(file, "\n"); 00251 00252 fprintf(file, "# ---------------------------------------------- "); 00253 fprintf(file, "%2d.4 Body\n", number); 00254 if (statement->body != NULL) { 00255 fprintf(file, "# Statement body is provided\n"); 00256 fprintf(file, "1\n"); 00257 osl_generic_print(file, statement->body); 00258 } 00259 else { 00260 fprintf(file, "# Statement body is not provided\n"); 00261 fprintf(file, "0\n"); 00262 } 00263 00264 fprintf(file, "\n"); 00265 00266 // If necessary, switch back iterator names. 00267 if (iterators_backedup) { 00268 iterators_backedup = 0; 00269 names->iterators = iterators_backup; 00270 } 00271 00272 statement = statement->next; 00273 number++; 00274 } 00275 00276 if (generated_names) 00277 osl_names_free(names); 00278 } 00279 00280 00288 void osl_statement_print(FILE * file, osl_statement_p statement) { 00289 00290 osl_statement_pprint(file, statement, NULL); 00291 } 00292 00293 00294 /***************************************************************************** 00295 * Reading function * 00296 *****************************************************************************/ 00297 00298 00308 static 00309 void osl_statement_dispatch(osl_statement_p stmt, osl_relation_list_p list) { 00310 osl_relation_list_p domain_list; 00311 osl_relation_list_p scattering_list; 00312 int nb_domains, nb_scattering, nb_accesses; 00313 00314 // Domain. 00315 domain_list = osl_relation_list_filter(list, OSL_TYPE_DOMAIN); 00316 nb_domains = osl_relation_list_count(domain_list); 00317 if (nb_domains > 1) 00318 OSL_error("more than one domain for a statement"); 00319 00320 if (domain_list != NULL) { 00321 stmt->domain = domain_list->elt; 00322 domain_list->elt = NULL; 00323 osl_relation_list_free(domain_list); 00324 } 00325 else { 00326 stmt->domain = NULL; 00327 } 00328 00329 // Scattering. 00330 scattering_list=osl_relation_list_filter(list,OSL_TYPE_SCATTERING); 00331 nb_scattering = osl_relation_list_count(scattering_list); 00332 if (nb_scattering > 1) 00333 OSL_error("more than one scattering relation for a statement"); 00334 00335 if (scattering_list != NULL) { 00336 stmt->scattering = scattering_list->elt; 00337 scattering_list->elt = NULL; 00338 osl_relation_list_free(scattering_list); 00339 } 00340 else { 00341 stmt->scattering = NULL; 00342 } 00343 00344 // Access. 00345 stmt->access = osl_relation_list_filter(list, OSL_TYPE_ACCESS); 00346 nb_accesses = osl_relation_list_count(stmt->access); 00347 00348 if ((nb_domains + nb_scattering + nb_accesses) != 00349 (osl_relation_list_count(list))) 00350 OSL_error("unexpected relation type to define a statement"); 00351 00352 osl_relation_list_free(list); 00353 } 00354 00355 00365 osl_statement_p osl_statement_pread(FILE * file, osl_interface_p registry, 00366 int precision) { 00367 osl_statement_p stmt = osl_statement_malloc(); 00368 osl_relation_list_p list; 00369 00370 if (file) { 00371 // Read all statement relations. 00372 list = osl_relation_list_pread(file, precision); 00373 00374 // Store relations at the right place according to their type. 00375 osl_statement_dispatch(stmt, list); 00376 00377 // Read the body information. 00378 if (osl_util_read_int(file, NULL) > 0) 00379 stmt->body = osl_generic_read_one(file, registry); 00380 } 00381 00382 return stmt; 00383 } 00384 00385 00394 osl_statement_p osl_statement_read(FILE * foo) { 00395 int precision = osl_util_get_precision(); 00396 osl_interface_p registry = osl_interface_get_default_registry(); 00397 osl_statement_p statement = osl_statement_pread(foo, registry, precision); 00398 00399 osl_interface_free(registry); 00400 return statement; 00401 } 00402 00403 00404 /*+*************************************************************************** 00405 * Memory allocation/deallocation functions * 00406 *****************************************************************************/ 00407 00408 00416 osl_statement_p osl_statement_malloc() { 00417 osl_statement_p statement; 00418 00419 OSL_malloc(statement, osl_statement_p, sizeof(osl_statement_t)); 00420 statement->domain = NULL; 00421 statement->scattering = NULL; 00422 statement->access = NULL; 00423 statement->body = NULL; 00424 statement->next = NULL; 00425 00426 return statement; 00427 } 00428 00429 00436 void osl_statement_free(osl_statement_p statement) { 00437 osl_statement_p next; 00438 00439 while (statement != NULL) { 00440 next = statement->next; 00441 osl_relation_free(statement->domain); 00442 osl_relation_free(statement->scattering); 00443 osl_relation_list_free(statement->access); 00444 osl_generic_free(statement->body); 00445 00446 free(statement); 00447 statement = next; 00448 } 00449 } 00450 00451 00452 /*+*************************************************************************** 00453 * Processing functions * 00454 *****************************************************************************/ 00455 00456 00464 void osl_statement_add(osl_statement_p * location, 00465 osl_statement_p statement) { 00466 while (*location != NULL) 00467 location = &((*location)->next); 00468 00469 *location = statement; 00470 } 00471 00472 00480 int osl_statement_number(osl_statement_p statement) { 00481 int number = 0; 00482 00483 while (statement != NULL) { 00484 number++; 00485 statement = statement->next; 00486 } 00487 return number; 00488 } 00489 00490 00498 osl_statement_p osl_statement_clone(osl_statement_p statement) { 00499 int first = 1; 00500 osl_statement_p clone = NULL, node, previous = NULL; 00501 00502 while (statement != NULL) { 00503 node = osl_statement_malloc(); 00504 node->domain = osl_relation_clone(statement->domain); 00505 node->scattering = osl_relation_clone(statement->scattering); 00506 node->access = osl_relation_list_clone(statement->access); 00507 node->body = osl_generic_clone(statement->body); 00508 node->next = NULL; 00509 00510 if (first) { 00511 first = 0; 00512 clone = node; 00513 previous = node; 00514 } 00515 else { 00516 previous->next = node; 00517 previous = previous->next; 00518 } 00519 00520 statement = statement->next; 00521 } 00522 00523 return clone; 00524 } 00525 00526 00535 int osl_statement_equal(osl_statement_p s1, osl_statement_p s2) { 00536 00537 if (s1 == s2) 00538 return 1; 00539 00540 if (((s1->next != NULL) && (s2->next == NULL)) || 00541 ((s1->next == NULL) && (s2->next != NULL))) { 00542 OSL_info("statements are not the same"); 00543 return 0; 00544 } 00545 00546 if ((s1->next != NULL) && (s2->next != NULL)) { 00547 if (!osl_statement_equal(s1->next, s2->next)) { 00548 OSL_info("number of statements is not the same"); 00549 return 0; 00550 } 00551 } 00552 00553 if (!osl_relation_equal(s1->domain, s2->domain)) { 00554 OSL_info("statement domains are not the same"); 00555 return 0; 00556 } 00557 00558 if (!osl_relation_equal(s1->scattering, s2->scattering)) { 00559 OSL_info("statement scatterings are not the same"); 00560 return 0; 00561 } 00562 00563 if (!osl_relation_list_equal(s1->access, s2->access)) { 00564 OSL_info("statement accesses are not the same"); 00565 return 0; 00566 } 00567 00568 if (!osl_generic_equal(s1->body, s2->body)) { 00569 OSL_info("statement bodies are not the same"); 00570 return 0; 00571 } 00572 00573 return 1; 00574 } 00575 00576 00587 int osl_statement_integrity_check(osl_statement_p statement, 00588 int expected_nb_parameters) { 00589 int expected_nb_iterators; 00590 00591 while (statement != NULL) { 00592 // Check the domain. 00593 if (!osl_relation_integrity_check(statement->domain, 00594 OSL_TYPE_DOMAIN, 00595 OSL_UNDEFINED, 00596 0, 00597 expected_nb_parameters)) { 00598 return 0; 00599 } 00600 00601 // Get the number of iterators. 00602 if (statement->domain != NULL) 00603 expected_nb_iterators = statement->domain->nb_output_dims; 00604 else 00605 expected_nb_iterators = OSL_UNDEFINED; 00606 00607 // Check the scattering relation. 00608 if (!osl_relation_integrity_check(statement->scattering, 00609 OSL_TYPE_SCATTERING, 00610 OSL_UNDEFINED, 00611 expected_nb_iterators, 00612 expected_nb_parameters)) { 00613 return 0; 00614 } 00615 00616 // Check the access relations. 00617 if (!osl_relation_list_integrity_check(statement->access, 00618 OSL_TYPE_ACCESS, 00619 OSL_UNDEFINED, 00620 expected_nb_iterators, 00621 expected_nb_parameters)) { 00622 return 0; 00623 } 00624 00625 // Check the statement body. 00626 if ((expected_nb_iterators != OSL_UNDEFINED) && 00627 (osl_generic_has_URI(statement->body, OSL_URI_BODY)) && 00628 (((osl_body_p)(statement->body->data))->iterators != NULL) && 00629 (expected_nb_iterators != osl_strings_size( 00630 ((osl_body_p)(statement->body->data))->iterators))) { 00631 OSL_warning("unexpected number of original iterators"); 00632 return 0; 00633 } 00634 00635 statement = statement->next; 00636 } 00637 00638 return 1; 00639 } 00640 00641 00649 int osl_statement_get_nb_iterators(osl_statement_p statement) { 00650 00651 if (statement->domain == NULL) { 00652 OSL_warning("no statement domain, assuming 0 iterators"); 00653 return 0; 00654 } 00655 else { 00656 return statement->domain->nb_output_dims; 00657 } 00658 } 00659 00660 00679 void osl_statement_get_attributes(osl_statement_p statement, 00680 int * nb_parameters, 00681 int * nb_iterators, 00682 int * nb_scattdims, 00683 int * nb_localdims, 00684 int * array_id) { 00685 int local_nb_parameters = OSL_UNDEFINED; 00686 int local_nb_iterators = OSL_UNDEFINED; 00687 int local_nb_scattdims = OSL_UNDEFINED; 00688 int local_nb_localdims = OSL_UNDEFINED; 00689 int local_array_id = OSL_UNDEFINED; 00690 00691 while (statement != NULL) { 00692 osl_relation_get_attributes(statement->domain, 00693 &local_nb_parameters, 00694 &local_nb_iterators, 00695 &local_nb_scattdims, 00696 &local_nb_localdims, 00697 &local_array_id); 00698 00699 osl_relation_get_attributes(statement->scattering, 00700 &local_nb_parameters, 00701 &local_nb_iterators, 00702 &local_nb_scattdims, 00703 &local_nb_localdims, 00704 &local_array_id); 00705 00706 osl_relation_list_get_attributes(statement->access, 00707 &local_nb_parameters, 00708 &local_nb_iterators, 00709 &local_nb_scattdims, 00710 &local_nb_localdims, 00711 &local_array_id); 00712 // Update. 00713 *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters); 00714 *nb_iterators = OSL_max(*nb_iterators, local_nb_iterators); 00715 *nb_scattdims = OSL_max(*nb_scattdims, local_nb_scattdims); 00716 *nb_localdims = OSL_max(*nb_localdims, local_nb_localdims); 00717 *array_id = OSL_max(*array_id, local_array_id); 00718 statement = statement->next; 00719 } 00720 } 00721