2 /*+-----------------------------------------------------------------**
4 **-----------------------------------------------------------------**
5 ** extensions/loop.c **
6 **-----------------------------------------------------------------**
7 ** First version: 03/06/2013 **
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 *****************************************************************************/
68 #include <osl/macros.h>
70 #include <osl/strings.h>
71 #include <osl/interface.h>
72 #include <osl/extensions/loop.h>
75 /*+***************************************************************************
76 * Structure display function *
77 *****************************************************************************/
81 * osl_loop_idump function:
82 * this function displays an osl_loop_t structure (loop) into a file
83 * (file, possibly stdout) in a way that trends to be understandable. It
84 * includes an indentation level (level) in order to work with others
87 * \param[in] file The file where the information has to be printed.
88 * \param[in] loop The loop structure to print.
89 * \param[in] level Number of spaces before printing, for each line.
91 void osl_loop_idump(FILE * file
, osl_loop_p loop
, int level
) {
92 int i
, j
, first
= 1, number
=1;
94 // Go to the right level.
95 for (j
= 0; j
< level
; j
++)
99 fprintf(file
, "+-- osl_loop_t\n");
101 fprintf(file
, "+-- NULL loop\n");
103 while (loop
!= NULL
) {
104 // Go to the right level.
106 // Go to the right level.
107 for (j
= 0; j
< level
; j
++)
108 fprintf(file
, "|\t");
110 fprintf(file
, "| osl_loop_t (node %d)\n", number
);
116 for (j
= 0; j
<= level
+1; j
++)
117 fprintf(file
, "|\t");
120 // Display the number of names.
121 for (j
= 0; j
<= level
; j
++)
122 fprintf(file
, "|\t");
123 fprintf(file
, "+--iterator: %s\n", loop
->iter
);
125 for (j
= 0; j
<= level
; j
++)
126 fprintf(file
, "|\t");
127 fprintf(file
, "+--nb_stmts: %d\n", loop
->nb_stmts
);
129 // Display the id/name.
130 for (j
= 0; j
<= level
; j
++)
131 fprintf(file
, "|\t");
132 fprintf(file
, "+--stmt_ids:");
133 for(i
= 0; i
< loop
->nb_stmts
; i
++) {
134 // Go to the right level.
135 fprintf(file
, "%2d, ", loop
->stmt_ids
[i
]);
140 for (j
= 0; j
<= level
; j
++)
141 fprintf(file
, "|\t");
142 fprintf(file
, "+--private_vars: %s\n", loop
->private_vars
);
144 for (j
= 0; j
<= level
; j
++)
145 fprintf(file
, "|\t");
146 fprintf(file
, "+--directive: %d\n", loop
->directive
);
148 for (j
= 0; j
<= level
; j
++)
149 fprintf(file
, "|\t");
150 fprintf(file
, "+--user: %s\n", loop
->user
);
157 for (j
= 0; j
<= level
; j
++)
158 fprintf(file
, "|\t");
159 fprintf(file
, "V\n");
164 for (j
= 0; j
<= level
; j
++)
165 fprintf(file
, "|\t");
171 * osl_loop_dump function:
172 * this function prints the content of an osl_loop_t structure
173 * (*loop) into a file (file, possibly stdout).
175 * \param[in] file The file where the information has to be printed.
176 * \param[in] loop The loop structure to print.
178 void osl_loop_dump(FILE * file
, osl_loop_p loop
) {
179 osl_loop_idump(file
, loop
, 0);
184 * osl_loop_sprint function:
185 * this function prints the content of an osl_loop_t structure
186 * (*loop) into a string (returned) in the OpenScop textual format.
187 * \param[in] loop The loop structure to print.
188 * \return A string containing the OpenScop dump of the loop structure.
190 char * osl_loop_sprint(osl_loop_p loop
) {
193 int high_water_mark
= OSL_MAX_STRING
;
195 char buffer
[OSL_MAX_STRING
];
197 OSL_malloc(string
, char *, high_water_mark
* sizeof(char));
200 sprintf(buffer
, "# Number of loops\n%d\n",osl_loop_count(loop
));
201 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
203 while (loop
!= NULL
) {
204 sprintf(buffer
, "# ===========================================\n");
205 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
207 sprintf(buffer
, "# Loop number %d \n", ++nloop
);
208 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
210 sprintf(buffer
, "# Iterator name\n");
211 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
212 sprintf(buffer
, "%s\n", loop
->iter
);
213 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
215 sprintf(buffer
, "# Number of stmts\n");
216 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
217 sprintf(buffer
, "%d\n", loop
->nb_stmts
);
218 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
220 if (loop
->nb_stmts
) {
221 sprintf(buffer
, "# Statement identifiers\n");
222 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
224 for (i
= 0; i
< loop
->nb_stmts
; i
++) {
225 sprintf(buffer
, "%d\n", loop
->stmt_ids
[i
]);
226 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
229 sprintf(buffer
, "# Private variables\n");
230 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
231 sprintf(buffer
, "%s\n", loop
->private_vars
);
232 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
234 sprintf(buffer
, "# Directive\n");
235 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
236 sprintf(buffer
, "%d", loop
->directive
);
237 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
239 // special case for OSL_LOOP_DIRECTIVE_USER
240 if (loop
->directive
== OSL_LOOP_DIRECTIVE_USER
) {
241 sprintf(buffer
, " %s", loop
->user
);
242 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
244 sprintf(buffer
, "\n");
245 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
250 OSL_realloc(string
, char *, (strlen(string
) + 1) * sizeof(char));
255 /*****************************************************************************
257 *****************************************************************************/
261 * osl_loop_sread function:
262 * this function reads a loop structure from a string complying to the
263 * OpenScop textual format and returns a pointer to this loop structure.
264 * The input parameter is updated to the position in the input string this
265 * function reaches right after reading the comment structure.
267 * \param[in,out] input The input string where to find an loop structure.
268 * Updated to the position after what has been read.
269 * \return A pointer to the loop structure that has been read.
271 osl_loop_p
osl_loop_sread(char **input
) {
278 OSL_debug("no loop optional tag");
282 // Find the number of names provided.
283 nb_loops
= osl_util_read_int(NULL
, input
);
287 // Allocate the array of id and names.
288 head
= loop
= osl_loop_malloc();
290 while (nb_loops
!= 0) {
292 loop
->iter
= osl_util_read_string(NULL
, input
);
293 loop
->nb_stmts
= osl_util_read_int(NULL
, input
);
295 OSL_malloc(loop
->stmt_ids
, int *, loop
->nb_stmts
* sizeof(int));
296 for (i
= 0; i
< loop
->nb_stmts
; i
++)
297 loop
->stmt_ids
[i
] = osl_util_read_int(NULL
, input
);
299 loop
->private_vars
= osl_util_read_line(NULL
, input
);
300 if (!strcmp(loop
->private_vars
, "(null)")) {
301 free(loop
->private_vars
);
302 loop
->private_vars
=NULL
;
305 loop
->directive
= osl_util_read_int(NULL
, input
);
307 // special case for OSL_LOOP_DIRECTIVE_USER
308 if (loop
->directive
== OSL_LOOP_DIRECTIVE_USER
) {
309 loop
->user
= osl_util_read_line(NULL
, input
);
310 if (!strcmp(loop
->user
, "(null)")) {
318 loop
->next
= osl_loop_malloc ();
327 /*+***************************************************************************
328 * Memory allocation/deallocation function *
329 *****************************************************************************/
333 * osl_loop_malloc function:
334 * this function allocates the memory space for an osl_loop_t
335 * structure and sets its fields with default values. Then it returns a
336 * pointer to the allocated space.
338 * \return A pointer to an empty loop structure with fields set to
341 osl_loop_p
osl_loop_malloc() {
344 OSL_malloc(loop
, osl_loop_p
, sizeof(osl_loop_t
));
347 loop
->stmt_ids
= NULL
;
348 loop
->private_vars
= NULL
;
358 * osl_loop_free function:
359 * this function frees the allocated memory for an loop structure.
361 * \param[in,out] loop The pointer to the loop structure we want to free.
363 void osl_loop_free(osl_loop_p loop
) {
365 while (loop
!= NULL
) {
366 osl_loop_p tmp
= loop
;
368 if (loop
->iter
) free(loop
->iter
);
369 if (loop
->stmt_ids
) free(loop
->stmt_ids
);
370 if (loop
->private_vars
) free(loop
->private_vars
);
371 if (loop
->user
) free(loop
->user
);
380 /*+***************************************************************************
381 * Processing functions *
382 *****************************************************************************/
386 * osl_loop_clone_one function:
387 * this function builds and returns a "hard copy" (not a pointer copy) of
388 * "one" (and not the whole list) osl_loop_t data structure.
390 * \param[in] loop The pointer to the loop structure to clone.
391 * \return A pointer to the clone of the loop structure.
393 osl_loop_p
osl_loop_clone_one(osl_loop_p loop
) {
400 clone
= osl_loop_malloc();
401 OSL_strdup(clone
->iter
, loop
->iter
);
402 clone
->nb_stmts
= loop
->nb_stmts
;
403 OSL_malloc(clone
->stmt_ids
, int *, loop
->nb_stmts
* sizeof(int));
405 for (i
= 0; i
< loop
->nb_stmts
; i
++) {
406 clone
->stmt_ids
[i
] = loop
->stmt_ids
[i
];
409 clone
->directive
= loop
->directive
;
411 if(loop
->private_vars
!= NULL
)
412 OSL_strdup(clone
->private_vars
, loop
->private_vars
);
414 if(loop
->user
!= NULL
)
415 OSL_strdup(clone
->user
, loop
->user
);
421 * osl_loop_clone function:
422 * this function builds and returns a "hard copy" (not a pointer copy) of a
423 * list of osl_loop_t data structures.
425 * \param[in] loop The pointer to the list of loop structure to clone.
426 * \return A pointer to the clone of list of the loop structure.
428 osl_loop_p
osl_loop_clone(osl_loop_p loop
) {
429 osl_loop_p clone
= NULL
;
430 osl_loop_p head
= NULL
;
438 head
= clone
= osl_loop_clone_one(loop
);
441 clone
->next
= osl_loop_clone_one(loop
);
452 * osl_loop_equal_one function:
453 * this function returns true if the two loop structures are the same
454 * (content-wise), false otherwise. This functions considers two loop
455 * structures as equal if the order of the array names differ, however
456 * the identifiers and names must be the same.
458 * \param[in] a1 The first loop structure.
459 * \param[in] a2 The second loop structure.
460 * \return 1 if a1 and a2 are the same (content-wise), 0 otherwise.
462 int osl_loop_equal_one(osl_loop_p a1
, osl_loop_p a2
) {
468 if (((a1
== NULL
) && (a2
!= NULL
)) || ((a1
!= NULL
) && (a2
== NULL
))) {
469 //OSL_info("loops are not the same (compare with NULL)");
473 // Check whether the number of names is the same.
474 if (a1
->nb_stmts
!= a2
->nb_stmts
) {
475 //OSL_info("loops are not the same (nb_stmts)");
479 if (strcmp(a1
->iter
, a2
->iter
)) {
480 //OSL_info("loops are not the same (iter name)");
483 // We accept a different order of the names, as long as the identifiers
485 for (i
= 0; i
< a1
->nb_stmts
; i
++) {
487 for (j
= 0; j
< a2
->nb_stmts
; j
++) {
488 if (a1
->stmt_ids
[i
] == a2
->stmt_ids
[j
]) {
494 //OSL_info("loop are not the same (stmt ids)");
499 //TODO: necessarily same ???
500 if (a1
->private_vars
!= a2
->private_vars
) { // NULL check
501 if (strcmp(a1
->private_vars
, a2
->private_vars
)) {
502 //OSL_info("loops are not the same (private vars)");
507 //TODO: necessarily same ???
508 if (a1
->directive
!= a2
->directive
) {
509 //OSL_info("loops are not the same (directive)");
513 if (a1
->user
!= a2
->user
) { // NULL check
514 if (strcmp(a1
->user
, a2
->user
)) {
523 * osl_loop_equal function:
524 * this function returns true if the two loop lists are the same
525 * (content-wise), false otherwise. Two lists are equal if one contains
526 * all the elements of the other and vice versa. The exact order of the
527 * nodes is not taken into account by this function.
529 * \param[in] a1 The first loop list.
530 * \param[in] a2 The second loop list.
531 * \return 1 if a1 and a2 are the same (content-wise), 0 otherwise.
533 int osl_loop_equal(osl_loop_p a1
, osl_loop_p a2
) {
539 if (((a1
== NULL
) && (a2
!= NULL
)) || ((a1
!= NULL
) && (a2
== NULL
))) {
540 OSL_info("lists of loops are not the same (compare with NULL)");
544 if (osl_loop_count(a1
) != osl_loop_count(a2
)) {
545 OSL_info("list of loops are not the same");
551 osl_loop_p temp
= a2
;
554 if(osl_loop_equal_one(a1
, temp
)==1){
562 OSL_info("list of loops are not the same");
573 * osl_loop_interface function:
574 * this function creates an interface structure corresponding to the loop
575 * extension and returns it.
577 * \return An interface structure for the loop extension.
579 osl_interface_p
osl_loop_interface() {
580 osl_interface_p interface
= osl_interface_malloc();
582 OSL_strdup(interface
->URI
, OSL_URI_LOOP
);
583 interface
->idump
= (osl_idump_f
)osl_loop_idump
;
584 interface
->sprint
= (osl_sprint_f
)osl_loop_sprint
;
585 interface
->sread
= (osl_sread_f
)osl_loop_sread
;
586 interface
->malloc
= (osl_malloc_f
)osl_loop_malloc
;
587 interface
->free
= (osl_free_f
)osl_loop_free
;
588 interface
->clone
= (osl_clone_f
)osl_loop_clone
;
589 interface
->equal
= (osl_equal_f
)osl_loop_equal
;
596 * osl_loop_add function:
597 * this function adds a loop structure at the end of the list
599 * \param[in,out] ll Pointer to a list of loops.
600 * \param[in] loop Pointer to the loop structure to be added.
602 void osl_loop_add(osl_loop_p loop
, osl_loop_p
*ll
) {
613 * this function returns the number of elements in the list
615 * \param[in] ll Pointer to a list of loops.
616 * \return Number of elements in the list
618 int osl_loop_count(osl_loop_p ll
) {