OpenScop 0.8.1

statement.c

Go to the documentation of this file.
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