OpenScop  0.9.0
dependence.c
Go to the documentation of this file.
00001 
00002     /*+-----------------------------------------------------------------**
00003      **                       OpenScop Library                          **
00004      **-----------------------------------------------------------------**
00005      **                      extensions/dependence.h                    **
00006      **-----------------------------------------------------------------**
00007      **                   First version: 02/07/2012                     **
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 #include <stdlib.h>
00064 #include <stdio.h>
00065 #include <string.h>
00066 #include <osl/macros.h>
00067 #include <osl/scop.h>
00068 #include <osl/statement.h>
00069 #include <osl/relation.h>
00070 #include <osl/names.h>
00071 #include <osl/util.h>
00072 #include <osl/extensions/dependence.h>
00073 
00078 /******************************************************************************
00079  *                          Structure display function                        *
00080  ******************************************************************************/
00081 
00082 
00092 void osl_dependence_idump(FILE* file,
00093                             osl_dependence_p dependence,
00094                             int level) {
00095   int j, first = 1;
00096   osl_statement_p tmp;
00097 
00098   if (dependence != NULL) { /* Go to the right level. */
00099     for (j=0; j<level; j++)
00100       fprintf(file, "|\t");
00101     fprintf(file, "+-- osl_dependence_p\n");
00102   } else {
00103     for (j=0; j<level; j++)
00104     fprintf(file, "|\t");
00105     fprintf(file, "+-- NULL dependence\n");
00106   }
00107 
00108   while (dependence != NULL) {
00109     if (!first) { /* Go to the right level. */
00110       for (j=0; j<level; j++)
00111         fprintf(file, "|\t");
00112       fprintf(file, "|   osl_dependence_p\n");
00113     } else {
00114       first = 0;
00115     }
00116 
00117     /* A blank line. */
00118     for (j=0; j<=level+1; j++)
00119       fprintf(file, "|\t");
00120     fprintf(file, "\n");
00121 
00122     /* Go to the right level and print the type. */
00123     for (j=0; j<=level; j++)
00124       fprintf(file, "|\t");
00125     fprintf(file, "Type: ");
00126     switch (dependence->type) {
00127       case OSL_UNDEFINED : fprintf(file, "UNSET\n");        break;
00128       case OSL_DEPENDENCE_RAW   : fprintf(file, "RAW (flow)\n");   break;
00129       case OSL_DEPENDENCE_WAR   : fprintf(file, "WAR (anti)\n");   break;
00130       case OSL_DEPENDENCE_WAW   : fprintf(file, "WAW (output)\n"); break;
00131       case OSL_DEPENDENCE_RAR   : fprintf(file, "RAR (input)\n");  break;
00132       case OSL_DEPENDENCE_RAW_SCALPRIV   : 
00133                    fprintf(file, "RAW_SCALPRIV (scalar priv)\n");  break;
00134       default : fprintf(file, "unknown\n"); break;
00135     }
00136 
00137     /* A blank line. */
00138     for (j=0; j<=level+1; j++)
00139       fprintf(file, "|\t");
00140     fprintf(file, "\n");
00141 
00142     /* Go to the right level and print the depth. */
00143     for (j=0; j<=level; j++)
00144       fprintf(file, "|\t");
00145     fprintf(file, "Depth: %d\n", dependence->depth);
00146 
00147     /* A blank line. */
00148     for (j=0; j<=level+1; j++)
00149       fprintf(file, "|\t");
00150     fprintf(file, "\n");
00151     
00152     /* Ref source and target */
00153     for (j=0; j<=level; j++)
00154       fprintf(file, "|\t");
00155     fprintf(file, "Ref source: %d, Ref target: %d\n",
00156             dependence->ref_source, dependence->ref_target);
00157     
00158     /* A blank line. */
00159     for (j=0; j<=level+1; j++)
00160       fprintf(file, "|\t");
00161     fprintf(file, "\n");
00162 
00163     /* Print the source statement. */
00164     for (j=0; j<=level; j++)
00165       fprintf(file, "|\t");
00166     fprintf(file, "Statement label: %d\n", dependence->label_source);
00167     tmp = dependence->stmt_source_ptr->next;
00168     dependence->stmt_source_ptr->next = NULL;
00169     osl_statement_idump(file, dependence->stmt_source_ptr, level+1);
00170     dependence->stmt_source_ptr->next = tmp;
00171 
00172     /* Print the target statement. */
00173     for (j=0; j<=level; j++)
00174       fprintf(file, "|\t");
00175     fprintf(file, "Target label: %d\n", dependence->label_target);
00176     tmp = dependence->stmt_target_ptr->next;
00177     dependence->stmt_target_ptr->next = NULL;
00178     osl_statement_idump(file, dependence->stmt_target_ptr, level+1);
00179     dependence->stmt_target_ptr->next = tmp;
00180 
00181     /* Print the dependence polyhedron. */
00182     for (j=0; j<=level; j++)
00183       fprintf(file, "|\t");
00184     fprintf(file, "%d %d %d %d %d %d %d %d\n",
00185             dependence->source_nb_output_dims_domain,
00186             dependence->source_nb_output_dims_access,
00187             dependence->target_nb_output_dims_domain,
00188             dependence->target_nb_output_dims_access,
00189             dependence->source_nb_local_dims_domain,
00190             dependence->source_nb_local_dims_access,
00191             dependence->target_nb_local_dims_domain,
00192             dependence->target_nb_local_dims_access);
00193     osl_relation_idump(file, dependence->domain, level+1);
00194 
00195     dependence = dependence->next;
00196 
00197     /* Next line. */
00198     if (dependence != NULL) {
00199       for (j=0; j<=level; j++)
00200         fprintf(file, "|\t");
00201       fprintf(file, "V\n");
00202     }
00203   }
00204 
00205   /* The last line. */
00206   for (j=0; j<=level; j++)
00207     fprintf(file, "|\t");
00208   fprintf(file, "\n");
00209 }
00210 
00211 
00217 void osl_dependence_dump(FILE * file, osl_dependence_p dependence) {
00218   osl_dependence_idump(file, dependence, 0);
00219 }
00220 
00221 
00226 void osl_dependence_print(FILE *file, osl_dependence_p dependence) {
00227   char *string = osl_dependence_sprint(dependence);
00228   fprintf(file, "%s\n", string);
00229   free(string);
00230 }
00231 
00232 
00238 char* osl_dependence_sprint(osl_dependence_p dependence) {
00239   
00240   osl_dependence_p tmp = dependence;
00241   int nb_deps;
00242   int buffer_size = 2048;
00243   char* buffer;
00244   char buff[2048];
00245   char* type;
00246   char* pbuffer;
00247   
00248   OSL_malloc(buffer, char*, buffer_size);
00249   buffer[0] = '\0';
00250   
00251   for (tmp = dependence, nb_deps = 0; tmp; tmp = tmp->next, ++nb_deps)
00252    ;
00253   snprintf(buff, OSL_MAX_STRING, "# Number of dependences\n%d\n", nb_deps);
00254   strcat(buffer, buff);
00255   
00256   if (nb_deps) {
00257     for (tmp = dependence, nb_deps = 1; tmp; tmp = tmp->next, ++nb_deps) {
00258       
00259       switch (tmp->type) {
00260         case OSL_UNDEFINED:
00261           type = "UNSET";
00262           break;
00263         case OSL_DEPENDENCE_RAW:
00264           type = "RAW #(flow)";
00265           break;
00266         case OSL_DEPENDENCE_WAR:
00267           type = "WAR #(anti)";
00268           break;
00269         case OSL_DEPENDENCE_WAW:
00270           type = "WAW #(output)";
00271           break;
00272         case OSL_DEPENDENCE_RAR:
00273           type = "RAR #(input)";
00274           break;
00275         case OSL_DEPENDENCE_RAW_SCALPRIV:
00276           type = "RAW_SCALPRIV #(scalar priv)";
00277           break;
00278         default:
00279           exit(1);
00280           break;
00281       }
00282 
00283       /* Output dependence information. */
00284       snprintf(buff, OSL_MAX_STRING, "# Description of dependence %d\n"
00285               "# type\n%s\n"
00286               "# From source statement id\n%d\n"
00287               "# To target statement id\n%d\n"
00288               "# Depth \n%d\n"
00289               "# From source access ref\n%d\n"
00290               "# To target access ref\n%d\n"
00291               "# Dependence domain\n",
00292               nb_deps, type,
00293               tmp->label_source,
00294               tmp->label_target,
00295               tmp->depth,
00296               tmp->ref_source,
00297               tmp->ref_target);
00298 
00299       osl_util_safe_strcat(&buffer, buff, &buffer_size);
00300       
00301       /* Output dependence domain. */
00302       pbuffer = osl_relation_sprint(tmp->domain);
00303       osl_util_safe_strcat(&buffer, pbuffer, &buffer_size);
00304       free(pbuffer);
00305     }
00306   }
00307   
00308   return buffer;
00309 }
00310 
00311 
00316 static
00317 osl_dependence_p osl_dependence_read_one_dep(char **input, int precision) {
00318   osl_dependence_p dep = osl_dependence_malloc();
00319   char *buffer;
00320   
00321   /* Dependence type */
00322   buffer = osl_util_read_string(NULL, input);
00323   if (! strcmp(buffer, "RAW"))
00324     dep->type = OSL_DEPENDENCE_RAW;
00325   else if (! strcmp(buffer, "RAR"))
00326     dep->type = OSL_DEPENDENCE_RAR;
00327   else if (! strcmp(buffer, "WAR"))
00328     dep->type = OSL_DEPENDENCE_WAR;
00329   else if (! strcmp(buffer, "WAW"))
00330     dep->type = OSL_DEPENDENCE_WAW;
00331   else if (! strcmp(buffer, "RAW_SCALPRIV"))
00332     dep->type = OSL_DEPENDENCE_RAW_SCALPRIV;
00333   free(buffer);
00334 
00335   /* # From source statement xxx */
00336   dep->label_source = osl_util_read_int(NULL, input);
00337   
00338   /* # To target statement xxx */
00339   dep->label_target = osl_util_read_int(NULL, input);
00340 
00341   /* # Depth */
00342   dep->depth = osl_util_read_int(NULL, input);
00343 
00344   /* # From source access ref */  
00345   dep->ref_source = osl_util_read_int(NULL, input);
00346   
00347   /* # To target access ref */
00348   dep->ref_target = osl_util_read_int(NULL, input);
00349   
00350   /* Read the osl_relation */
00351   dep->domain = osl_relation_psread(input, precision);
00352   
00353   return dep;
00354 }
00355 
00356 
00361 osl_dependence_p osl_dependence_sread(char **input) {
00362   int precision = osl_util_get_precision();
00363   return osl_dependence_psread(input, precision);
00364 }
00365 
00366 
00371 osl_dependence_p osl_dependence_psread(char **input, int precision) {
00372   osl_dependence_p first = NULL;
00373   osl_dependence_p currdep = NULL;
00374 
00375   if (*input == NULL) {
00376     OSL_debug("no dependence optional tag");
00377     return NULL;
00378   }
00379 
00380   int i;
00381   /* Get the number of dependences. */
00382   int nbdeps = osl_util_read_int(NULL, input);
00383 
00384   /* For each of them, read 1 and shift of the read size. */
00385   for (i = 0; i < nbdeps; i++) {
00386     osl_dependence_p adep = osl_dependence_read_one_dep(input, precision);
00387     if (first == NULL) {
00388       currdep = first = adep;
00389     } else {
00390       currdep->next = adep;
00391       currdep = currdep->next;
00392     }
00393   }
00394 
00395   return first;
00396 }
00397 
00398 
00399 /******************************************************************************
00400  *                         Memory deallocation function                       *
00401  ******************************************************************************/
00402 
00403 
00411 osl_dependence_p osl_dependence_malloc() {
00412   osl_dependence_p dependence;
00413 
00414   /* Memory allocation for the osl_dependence_p structure. */
00415   OSL_malloc(dependence, osl_dependence_p, sizeof(osl_dependence_t));
00416 
00417   /* We set the various fields with default values. */
00418   dependence->depth      = OSL_UNDEFINED;
00419   dependence->type       = OSL_UNDEFINED;
00420   dependence->label_source = OSL_UNDEFINED;
00421   dependence->label_target = OSL_UNDEFINED;
00422   dependence->ref_source = OSL_UNDEFINED;
00423   dependence->ref_target = OSL_UNDEFINED;
00424   dependence->domain     = NULL;
00425   dependence->next       = NULL;
00426   dependence->usr              = NULL;
00427   dependence->source_nb_output_dims_domain = OSL_UNDEFINED;
00428   dependence->source_nb_output_dims_access = OSL_UNDEFINED;
00429   dependence->target_nb_output_dims_domain = OSL_UNDEFINED;
00430   dependence->target_nb_output_dims_access = OSL_UNDEFINED;
00431   dependence->source_nb_local_dims_domain  = OSL_UNDEFINED;
00432   dependence->source_nb_local_dims_access  = OSL_UNDEFINED;
00433   dependence->target_nb_local_dims_domain  = OSL_UNDEFINED;
00434   dependence->target_nb_local_dims_access  = OSL_UNDEFINED;
00435   dependence->ref_source_access_ptr = NULL;
00436   dependence->ref_target_access_ptr = NULL;
00437   dependence->stmt_source_ptr     = NULL;
00438   dependence->stmt_target_ptr     = NULL;
00439 
00440   return dependence;
00441 }
00442 
00443 
00449 void osl_dependence_free(osl_dependence_p dependence) {
00450   osl_dependence_p next;
00451   while (dependence != NULL) {
00452     next = dependence->next;
00453     osl_relation_free(dependence->domain);
00454     free(dependence);
00455     dependence = next;
00456   }
00457 }
00458 
00459 
00460 /******************************************************************************
00461  *                            Processing functions                            *
00462  ******************************************************************************/
00463 
00464 
00473 osl_dependence_p osl_dependence_nclone(osl_dependence_p dep, int n) {
00474   int first = 1, i = 0;
00475   osl_dependence_p clone = NULL, node, previous = NULL;
00476 
00477   while ((dep != NULL) && ((n == -1) || (i < n))) {
00478     node = osl_dependence_malloc();
00479     node->stmt_source_ptr = dep->stmt_source_ptr;
00480     node->stmt_target_ptr = dep->stmt_target_ptr;
00481     node->depth = dep->depth;
00482     node->type = dep->type;
00483     node->label_source = dep->label_source;
00484     node->label_target = dep->label_target;
00485     node->ref_source = dep->ref_source;
00486     node->ref_target = dep->ref_target;
00487     node->domain     = osl_relation_clone(dep->domain);
00488     node->source_nb_output_dims_domain = dep->source_nb_output_dims_domain;
00489     node->source_nb_output_dims_access = dep->source_nb_output_dims_access;
00490     node->target_nb_output_dims_domain = dep->target_nb_output_dims_domain;
00491     node->target_nb_output_dims_access = dep->target_nb_output_dims_access;
00492     node->source_nb_local_dims_domain  = dep->source_nb_local_dims_domain;
00493     node->source_nb_local_dims_access  = dep->source_nb_local_dims_access;
00494     node->target_nb_local_dims_domain  = dep->target_nb_local_dims_domain;
00495     node->target_nb_local_dims_access  = dep->target_nb_local_dims_access;
00496     node->next       = NULL;
00497     node->usr        = NULL;
00498 
00499     if (first) {
00500       first = 0;
00501       clone = node;
00502       previous = node;
00503     }
00504     else {
00505       previous->next = node;
00506       previous = previous->next;
00507     }
00508 
00509     i++;
00510     dep = dep->next;
00511   }
00512 
00513   return clone;
00514 }
00515 
00516 
00524 osl_dependence_p osl_dependence_clone(osl_dependence_p dep) {
00525   return osl_dependence_nclone(dep, -1);
00526 }
00527 
00528 
00538 int osl_dependence_equal(osl_dependence_p d1, osl_dependence_p d2) {
00539 
00540   if (d1 == d2)
00541     return 1;
00542   
00543   if ((d1->next != NULL && d2->next == NULL) ||
00544       (d1->next == NULL && d2->next != NULL))
00545     return 0;
00546 
00547   if (d1->next != NULL && d2->next != NULL)
00548     if (!osl_dependence_equal(d1->next, d2->next))
00549       return 0;
00550     
00551   if (!osl_relation_equal(d1->domain, d2->domain))
00552     return 0;
00553 
00554   if (d1->label_source != d2->label_source ||
00555       d1->label_target != d2->label_target ||
00556       d1->ref_source   != d2->ref_source   ||
00557       d1->ref_target   != d2->ref_target   ||
00558       d1->depth        != d2->depth        ||
00559       d1->type         != d2->type         ||
00560       
00561       d1->source_nb_output_dims_domain != 
00562       d2->source_nb_output_dims_domain     ||
00563       
00564       d1->source_nb_output_dims_access != 
00565       d2->source_nb_output_dims_access     ||
00566       
00567       d1->target_nb_output_dims_domain != 
00568       d2->target_nb_output_dims_domain     || 
00569       
00570       d1->target_nb_output_dims_access !=
00571       d2->target_nb_output_dims_access     ||
00572       
00573       d1->source_nb_local_dims_domain !=
00574       d2->source_nb_local_dims_domain      ||
00575       
00576       d1->source_nb_local_dims_access !=
00577       d2->source_nb_local_dims_access      ||
00578       
00579       d1->target_nb_local_dims_domain !=
00580       d2->target_nb_local_dims_domain      ||
00581   
00582       d1->target_nb_local_dims_access != 
00583       d2->target_nb_local_dims_access)
00584     return 0;
00585 
00586   return 1;
00587 }
00588 
00589 
00599 void osl_dependence_add(osl_dependence_p* start,
00600                         osl_dependence_p* now,
00601                         osl_dependence_p dependence) {
00602   if (dependence != NULL) {
00603     if (*start == NULL) {
00604       *start = dependence;
00605       *now = *start;
00606     } else {
00607       (*now)->next = dependence;
00608       *now = (*now)->next;
00609     }
00610 
00611     while ((*now)->next != NULL)
00612       *now = (*now)->next;
00613   }
00614 }
00615 
00616 
00624 int osl_nb_dependences(osl_dependence_p deps) {
00625   osl_dependence_p dep = deps;
00626   int num = 0;
00627   while (dep != NULL) {
00628     num++;
00629     dep = dep->next;
00630   }
00631   return num;
00632 }
00633 
00634 
00641 osl_interface_p osl_dependence_interface() {
00642   osl_interface_p interface = osl_interface_malloc();
00643   
00644   OSL_strdup(interface->URI, OSL_URI_DEPENDENCE);
00645   interface->idump  = (osl_idump_f)osl_dependence_idump;
00646   interface->sprint = (osl_sprint_f)osl_dependence_sprint;
00647   interface->sread  = (osl_sread_f)osl_dependence_sread;
00648   interface->malloc = (osl_malloc_f)osl_dependence_malloc;
00649   interface->free   = (osl_free_f)osl_dependence_free;
00650   interface->clone  = (osl_clone_f)osl_dependence_clone;
00651   interface->equal  = (osl_equal_f)osl_dependence_equal;
00652 
00653   return interface;
00654 }