2
/*+-----------------------------------------------------------------**
4
**-----------------------------------------------------------------**
5
** extensions/dependence.h **
6
**-----------------------------------------------------------------**
7
** First version: 02/07/2012 **
8
**-----------------------------------------------------------------**
11
*****************************************************************************
12
* OpenScop: Structures and formats for polyhedral tools to talk together *
13
*****************************************************************************
14
* ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15
* / / / // // // // / / / // // / / // / /|,_, *
16
* / / / // // // // / / / // // / / // / / / /\ *
17
* |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18
* | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19
* | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20
* | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21
* | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22
* | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23
* | I | | | | e | | | | | | | | | | | | | \ \ \ *
24
* | T | | | | | | | | | | | | | | | | | \ \ \ *
25
* | E | | | | | | | | | | | | | | | | | \ \ \ *
26
* | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27
* | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28
* '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
30
* Copyright (C) 2008 University Paris-Sud 11 and INRIA *
32
* (3-clause BSD license) *
33
* Redistribution and use in source and binary forms, with or without *
34
* modification, are permitted provided that the following conditions *
37
* 1. Redistributions of source code must retain the above copyright notice, *
38
* this list of conditions and the following disclaimer. *
39
* 2. Redistributions in binary form must reproduce the above copyright *
40
* notice, this list of conditions and the following disclaimer in the *
41
* documentation and/or other materials provided with the distribution. *
42
* 3. The name of the author may not be used to endorse or promote products *
43
* derived from this software without specific prior written permission. *
45
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
56
* OpenScop Library, a library to manipulate OpenScop formats and data *
57
* structures. Written by: *
58
* Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59
* Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
61
*****************************************************************************/
66
#include <osl/macros.h>
68
#include <osl/statement.h>
69
#include <osl/relation.h>
70
#include <osl/names.h>
72
#include <osl/extensions/dependence.h>
75
* Most of these functions where extracted from candl and ported to osl
78
/******************************************************************************
79
* Structure display function *
80
******************************************************************************/
84
* osl_dependence_idump function:
85
* Displays a osl_dependence_p structure (dependence) into a file (file,
86
* possibly stdout) in a way that trends to be understandable without falling
87
* in a deep depression or, for the lucky ones, getting a headache... It
88
* includes an indentation level (level) in order to work with others
90
* - 18/09/2003: first version.
92
void osl_dependence_idump(FILE* file,
93
osl_dependence_p dependence,
98
if (dependence != NULL) { /* Go to the right level. */
99
for (j=0; j<level; j++)
100
fprintf(file, "|\t");
101
fprintf(file, "+-- osl_dependence_p\n");
103
for (j=0; j<level; j++)
104
fprintf(file, "|\t");
105
fprintf(file, "+-- NULL dependence\n");
108
while (dependence != NULL) {
109
if (!first) { /* Go to the right level. */
110
for (j=0; j<level; j++)
111
fprintf(file, "|\t");
112
fprintf(file, "| osl_dependence_p\n");
118
for (j=0; j<=level+1; j++)
119
fprintf(file, "|\t");
122
/* Go to the right level and print the type. */
123
for (j=0; j<=level; j++)
124
fprintf(file, "|\t");
125
fprintf(file, "Type: ");
126
switch (dependence->type) {
127
case OSL_UNDEFINED : fprintf(file, "UNSET\n"); break;
128
case OSL_DEPENDENCE_RAW : fprintf(file, "RAW (flow)\n"); break;
129
case OSL_DEPENDENCE_WAR : fprintf(file, "WAR (anti)\n"); break;
130
case OSL_DEPENDENCE_WAW : fprintf(file, "WAW (output)\n"); break;
131
case OSL_DEPENDENCE_RAR : fprintf(file, "RAR (input)\n"); break;
132
case OSL_DEPENDENCE_RAW_SCALPRIV :
133
fprintf(file, "RAW_SCALPRIV (scalar priv)\n"); break;
134
default : fprintf(file, "unknown\n"); break;
138
for (j=0; j<=level+1; j++)
139
fprintf(file, "|\t");
142
/* Go to the right level and print the depth. */
143
for (j=0; j<=level; j++)
144
fprintf(file, "|\t");
145
fprintf(file, "Depth: %d\n", dependence->depth);
148
for (j=0; j<=level+1; j++)
149
fprintf(file, "|\t");
152
/* Ref source and target */
153
for (j=0; j<=level; j++)
154
fprintf(file, "|\t");
155
fprintf(file, "Ref source: %d, Ref target: %d\n",
156
dependence->ref_source, dependence->ref_target);
159
for (j=0; j<=level+1; j++)
160
fprintf(file, "|\t");
163
/* Print the source statement. */
164
for (j=0; j<=level; j++)
165
fprintf(file, "|\t");
166
fprintf(file, "Statement label: %d\n", dependence->label_source);
167
tmp = dependence->stmt_source_ptr->next;
168
dependence->stmt_source_ptr->next = NULL;
169
osl_statement_idump(file, dependence->stmt_source_ptr, level+1);
170
dependence->stmt_source_ptr->next = tmp;
172
/* Print the target statement. */
173
for (j=0; j<=level; j++)
174
fprintf(file, "|\t");
175
fprintf(file, "Target label: %d\n", dependence->label_target);
176
tmp = dependence->stmt_target_ptr->next;
177
dependence->stmt_target_ptr->next = NULL;
178
osl_statement_idump(file, dependence->stmt_target_ptr, level+1);
179
dependence->stmt_target_ptr->next = tmp;
181
/* Print the dependence polyhedron. */
182
for (j=0; j<=level; j++)
183
fprintf(file, "|\t");
184
fprintf(file, "%d %d %d %d %d %d %d %d\n",
185
dependence->source_nb_output_dims_domain,
186
dependence->source_nb_output_dims_access,
187
dependence->target_nb_output_dims_domain,
188
dependence->target_nb_output_dims_access,
189
dependence->source_nb_local_dims_domain,
190
dependence->source_nb_local_dims_access,
191
dependence->target_nb_local_dims_domain,
192
dependence->target_nb_local_dims_access);
193
osl_relation_idump(file, dependence->domain, level+1);
195
dependence = dependence->next;
198
if (dependence != NULL) {
199
for (j=0; j<=level; j++)
200
fprintf(file, "|\t");
201
fprintf(file, "V\n");
206
for (j=0; j<=level; j++)
207
fprintf(file, "|\t");
213
* osl_dependence_dump function:
214
* This function prints the content of a osl_dependence_p structure (dependence)
215
* into a file (file, possibly stdout).
217
void osl_dependence_dump(FILE * file, osl_dependence_p dependence) {
218
osl_dependence_idump(file, dependence, 0);
223
* osl_dependence_print function:
224
* Print the dependence, formatted to fit the .scop representation.
226
void osl_dependence_print(FILE *file, osl_dependence_p dependence) {
227
char *string = osl_dependence_sprint(dependence);
228
fprintf(file, "%s\n", string);
234
* osl_dependence_sprint function:
235
* Returns a string containing the dependence, formatted to fit the
236
* .scop representation.
238
char* osl_dependence_sprint(osl_dependence_p dependence) {
240
osl_dependence_p tmp = dependence;
242
int buffer_size = 2048;
248
OSL_malloc(buffer, char*, buffer_size);
251
for (tmp = dependence, nb_deps = 0; tmp; tmp = tmp->next, ++nb_deps)
253
snprintf(buff, OSL_MAX_STRING, "# Number of dependences\n%d\n", nb_deps);
254
strcat(buffer, buff);
257
for (tmp = dependence, nb_deps = 1; tmp; tmp = tmp->next, ++nb_deps) {
263
case OSL_DEPENDENCE_RAW:
264
type = "RAW #(flow)";
266
case OSL_DEPENDENCE_WAR:
267
type = "WAR #(anti)";
269
case OSL_DEPENDENCE_WAW:
270
type = "WAW #(output)";
272
case OSL_DEPENDENCE_RAR:
273
type = "RAR #(input)";
275
case OSL_DEPENDENCE_RAW_SCALPRIV:
276
type = "RAW_SCALPRIV #(scalar priv)";
283
/* Output dependence information. */
284
snprintf(buff, OSL_MAX_STRING, "# Description of dependence %d\n"
286
"# From source statement id\n%d\n"
287
"# To target statement id\n%d\n"
289
"# From source access ref\n%d\n"
290
"# To target access ref\n%d\n"
291
"# Dependence domain\n",
299
osl_util_safe_strcat(&buffer, buff, &buffer_size);
301
/* Output dependence domain. */
302
pbuffer = osl_relation_sprint(tmp->domain);
303
osl_util_safe_strcat(&buffer, pbuffer, &buffer_size);
313
* osl_dependence_read_one_dep function:
314
* Read one dependence from a string.
317
osl_dependence_p osl_dependence_read_one_dep(char **input, int precision) {
318
osl_dependence_p dep = osl_dependence_malloc();
321
/* Dependence type */
322
buffer = osl_util_read_string(NULL, input);
323
if (! strcmp(buffer, "RAW"))
324
dep->type = OSL_DEPENDENCE_RAW;
325
else if (! strcmp(buffer, "RAR"))
326
dep->type = OSL_DEPENDENCE_RAR;
327
else if (! strcmp(buffer, "WAR"))
328
dep->type = OSL_DEPENDENCE_WAR;
329
else if (! strcmp(buffer, "WAW"))
330
dep->type = OSL_DEPENDENCE_WAW;
331
else if (! strcmp(buffer, "RAW_SCALPRIV"))
332
dep->type = OSL_DEPENDENCE_RAW_SCALPRIV;
335
/* # From source statement xxx */
336
dep->label_source = osl_util_read_int(NULL, input);
338
/* # To target statement xxx */
339
dep->label_target = osl_util_read_int(NULL, input);
342
dep->depth = osl_util_read_int(NULL, input);
344
/* # From source access ref */
345
dep->ref_source = osl_util_read_int(NULL, input);
347
/* # To target access ref */
348
dep->ref_target = osl_util_read_int(NULL, input);
350
/* Read the osl_relation */
351
dep->domain = osl_relation_psread(input, precision);
358
* osl_dependence_sread function:
359
* Retrieve a osl_dependence_p list from the option tag in the scop.
361
osl_dependence_p osl_dependence_sread(char **input) {
362
int precision = osl_util_get_precision();
363
return osl_dependence_psread(input, precision);
368
* osl_dependence_psread function
369
* Retrieve a osl_dependence_p list from the option tag in the scop.
371
osl_dependence_p osl_dependence_psread(char **input, int precision) {
372
osl_dependence_p first = NULL;
373
osl_dependence_p currdep = NULL;
375
if (*input == NULL) {
376
OSL_debug("no dependence optional tag");
381
/* Get the number of dependences. */
382
int nbdeps = osl_util_read_int(NULL, input);
384
/* For each of them, read 1 and shift of the read size. */
385
for (i = 0; i < nbdeps; i++) {
386
osl_dependence_p adep = osl_dependence_read_one_dep(input, precision);
388
currdep = first = adep;
390
currdep->next = adep;
391
currdep = currdep->next;
399
/******************************************************************************
400
* Memory deallocation function *
401
******************************************************************************/
405
* osl_dependence_malloc function:
406
* This function allocates the memory space for a osl_dependence_p structure and
407
* sets its fields with default values. Then it returns a pointer to the
409
* - 07/12/2005: first version.
411
osl_dependence_p osl_dependence_malloc() {
412
osl_dependence_p dependence;
414
/* Memory allocation for the osl_dependence_p structure. */
415
OSL_malloc(dependence, osl_dependence_p, sizeof(osl_dependence_t));
417
/* We set the various fields with default values. */
418
dependence->depth = OSL_UNDEFINED;
419
dependence->type = OSL_UNDEFINED;
420
dependence->label_source = OSL_UNDEFINED;
421
dependence->label_target = OSL_UNDEFINED;
422
dependence->ref_source = OSL_UNDEFINED;
423
dependence->ref_target = OSL_UNDEFINED;
424
dependence->domain = NULL;
425
dependence->next = NULL;
426
dependence->usr = NULL;
427
dependence->source_nb_output_dims_domain = OSL_UNDEFINED;
428
dependence->source_nb_output_dims_access = OSL_UNDEFINED;
429
dependence->target_nb_output_dims_domain = OSL_UNDEFINED;
430
dependence->target_nb_output_dims_access = OSL_UNDEFINED;
431
dependence->source_nb_local_dims_domain = OSL_UNDEFINED;
432
dependence->source_nb_local_dims_access = OSL_UNDEFINED;
433
dependence->target_nb_local_dims_domain = OSL_UNDEFINED;
434
dependence->target_nb_local_dims_access = OSL_UNDEFINED;
435
dependence->ref_source_access_ptr = NULL;
436
dependence->ref_target_access_ptr = NULL;
437
dependence->stmt_source_ptr = NULL;
438
dependence->stmt_target_ptr = NULL;
445
* osl_dependence_free function:
446
* This function frees the allocated memory for a osl_dependence_p structure.
447
* - 18/09/2003: first version.
449
void osl_dependence_free(osl_dependence_p dependence) {
450
osl_dependence_p next;
451
while (dependence != NULL) {
452
next = dependence->next;
453
osl_relation_free(dependence->domain);
460
/******************************************************************************
461
* Processing functions *
462
******************************************************************************/
466
* osl_dependence_nclone function:
467
* This function builds and returns a "hard copy" (not a pointer copy) of the
468
* n first elements of an osl_dependence_t list.
469
* \param statement The pointer to the dependence structure we want to clone.
470
* \param n The number of nodes we want to copy (-1 for infinity).
471
* \return The clone of the n first nodes of the dependence list.
473
osl_dependence_p osl_dependence_nclone(osl_dependence_p dep, int n) {
474
int first = 1, i = 0;
475
osl_dependence_p clone = NULL, node, previous = NULL;
477
while ((dep != NULL) && ((n == -1) || (i < n))) {
478
node = osl_dependence_malloc();
479
node->stmt_source_ptr = dep->stmt_source_ptr;
480
node->stmt_target_ptr = dep->stmt_target_ptr;
481
node->depth = dep->depth;
482
node->type = dep->type;
483
node->label_source = dep->label_source;
484
node->label_target = dep->label_target;
485
node->ref_source = dep->ref_source;
486
node->ref_target = dep->ref_target;
487
node->domain = osl_relation_clone(dep->domain);
488
node->source_nb_output_dims_domain = dep->source_nb_output_dims_domain;
489
node->source_nb_output_dims_access = dep->source_nb_output_dims_access;
490
node->target_nb_output_dims_domain = dep->target_nb_output_dims_domain;
491
node->target_nb_output_dims_access = dep->target_nb_output_dims_access;
492
node->source_nb_local_dims_domain = dep->source_nb_local_dims_domain;
493
node->source_nb_local_dims_access = dep->source_nb_local_dims_access;
494
node->target_nb_local_dims_domain = dep->target_nb_local_dims_domain;
495
node->target_nb_local_dims_access = dep->target_nb_local_dims_access;
505
previous->next = node;
506
previous = previous->next;
518
* osl_dependence_clone function:
519
* This functions builds and returns a "hard copy" (not a pointer copy) of an
520
* osl_dependence_t data structure provided as parameter.
521
* \param[in] statement The pointer to the dependence we want to clone.
522
* \return A pointer to the clone of the dependence provided as parameter.
524
osl_dependence_p osl_dependence_clone(osl_dependence_p dep) {
525
return osl_dependence_nclone(dep, -1);
530
* osl_dependence_equal function:
531
* this function returns true if the two dependences provided as parameters
532
* are the same, false otherwise (the usr field is not tested).
533
* NOTE: the different pointer to statements or relations are nto compared
534
* \param[in] d1 The first dependence.
535
* \param[in] d2 The second dependence.
536
* \return 1 if d1 and d2 are the same (content-wise), 0 otherwise.
538
int osl_dependence_equal(osl_dependence_p d1, osl_dependence_p d2) {
543
if ((d1->next != NULL && d2->next == NULL) ||
544
(d1->next == NULL && d2->next != NULL))
547
if (d1->next != NULL && d2->next != NULL)
548
if (!osl_dependence_equal(d1->next, d2->next))
551
if (!osl_relation_equal(d1->domain, d2->domain))
554
if (d1->label_source != d2->label_source ||
555
d1->label_target != d2->label_target ||
556
d1->ref_source != d2->ref_source ||
557
d1->ref_target != d2->ref_target ||
558
d1->depth != d2->depth ||
559
d1->type != d2->type ||
561
d1->source_nb_output_dims_domain !=
562
d2->source_nb_output_dims_domain ||
564
d1->source_nb_output_dims_access !=
565
d2->source_nb_output_dims_access ||
567
d1->target_nb_output_dims_domain !=
568
d2->target_nb_output_dims_domain ||
570
d1->target_nb_output_dims_access !=
571
d2->target_nb_output_dims_access ||
573
d1->source_nb_local_dims_domain !=
574
d2->source_nb_local_dims_domain ||
576
d1->source_nb_local_dims_access !=
577
d2->source_nb_local_dims_access ||
579
d1->target_nb_local_dims_domain !=
580
d2->target_nb_local_dims_domain ||
582
d1->target_nb_local_dims_access !=
583
d2->target_nb_local_dims_access)
591
* osl_dependence_add function:
592
* This function adds a osl_dependence_p structure (dependence) at a given place
593
* (now) of a NULL terminated list of osl_dependence_p structures. The beginning
594
* of this list is (start). This function updates (now) to the end of the loop
595
* list (loop), and updates (start) if the added element is the first one -that
596
* is when (start) is NULL-.
597
* - 18/09/2003: first version.
599
void osl_dependence_add(osl_dependence_p* start,
600
osl_dependence_p* now,
601
osl_dependence_p dependence) {
602
if (dependence != NULL) {
603
if (*start == NULL) {
607
(*now)->next = dependence;
611
while ((*now)->next != NULL)
618
* osl_nb_dependences function:
619
* This function returns the number of dependences in the dependence
621
* \param dependence The first dependence of the dependence list.
624
int osl_nb_dependences(osl_dependence_p deps) {
625
osl_dependence_p dep = deps;
627
while (dep != NULL) {
636
* osl_dependence_interface function:
637
* this function creates an interface structure corresponding to the dependence
638
* extension and returns it).
639
* \return An interface structure for the dependence extension.
641
osl_interface_p osl_dependence_interface() {
642
osl_interface_p interface = osl_interface_malloc();
644
interface->URI = strdup(OSL_URI_DEPENDENCE);
645
interface->idump = (osl_idump_f)osl_dependence_idump;
646
interface->sprint = (osl_sprint_f)osl_dependence_sprint;
647
interface->sread = (osl_sread_f)osl_dependence_sread;
648
interface->malloc = (osl_malloc_f)osl_dependence_malloc;
649
interface->free = (osl_free_f)osl_dependence_free;
650
interface->clone = (osl_clone_f)osl_dependence_clone;
651
interface->equal = (osl_equal_f)osl_dependence_equal;