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
);
153 for (j
= 0; j
<= level
; j
++)
154 fprintf(file
, "|\t");
155 fprintf(file
, "V\n");
160 for (j
= 0; j
<= level
; j
++)
161 fprintf(file
, "|\t");
167 * osl_loop_dump function:
168 * this function prints the content of an osl_loop_t structure
169 * (*loop) into a file (file, possibly stdout).
171 * \param[in] file The file where the information has to be printed.
172 * \param[in] loop The loop structure to print.
174 void osl_loop_dump(FILE * file
, osl_loop_p loop
) {
175 osl_loop_idump(file
, loop
, 0);
180 * osl_loop_sprint function:
181 * this function prints the content of an osl_loop_t structure
182 * (*loop) into a string (returned) in the OpenScop textual format.
183 * \param[in] loop The loop structure to print.
184 * \return A string containing the OpenScop dump of the loop structure.
186 char * osl_loop_sprint(osl_loop_p loop
) {
189 int high_water_mark
= OSL_MAX_STRING
;
191 char buffer
[OSL_MAX_STRING
];
193 OSL_malloc(string
, char *, high_water_mark
* sizeof(char));
196 sprintf(buffer
, "# Number of loops\n%d\n",osl_loop_count(loop
));
197 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
199 while (loop
!= NULL
) {
200 sprintf(buffer
, "# ===========================================\n");
201 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
203 sprintf(buffer
, "# Loop number %d \n", ++nloop
);
204 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
206 sprintf(buffer
, "# Iterator name\n");
207 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
208 sprintf(buffer
, "%s\n", loop
->iter
);
209 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
211 sprintf(buffer
, "# Number of stmts\n");
212 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
213 sprintf(buffer
, "%d\n", loop
->nb_stmts
);
214 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
216 if (loop
->nb_stmts
) {
217 sprintf(buffer
, "# Statement identifiers\n");
218 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
220 for (i
= 0; i
< loop
->nb_stmts
; i
++) {
221 sprintf(buffer
, "%d\n", loop
->stmt_ids
[i
]);
222 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
225 sprintf(buffer
, "# Private variables\n");
226 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
227 sprintf(buffer
, "%s\n", loop
->private_vars
);
228 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
230 sprintf(buffer
, "# Directive\n");
231 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
232 sprintf(buffer
, "%d\n", loop
->directive
);
233 osl_util_safe_strcat(&string
, buffer
, &high_water_mark
);
238 OSL_realloc(string
, char *, (strlen(string
) + 1) * sizeof(char));
243 /*****************************************************************************
245 *****************************************************************************/
249 * osl_loop_sread function:
250 * this function reads a loop structure from a string complying to the
251 * OpenScop textual format and returns a pointer to this loop structure.
252 * The input parameter is updated to the position in the input string this
253 * function reaches right after reading the comment structure.
255 * \param[in,out] input The input string where to find an loop structure.
256 * Updated to the position after what has been read.
257 * \return A pointer to the loop structure that has been read.
259 osl_loop_p
osl_loop_sread(char **input
) {
266 OSL_debug("no loop optional tag");
270 // Find the number of names provided.
271 nb_loops
= osl_util_read_int(NULL
, input
);
275 // Allocate the array of id and names.
276 head
= loop
= osl_loop_malloc();
278 while (nb_loops
!= 0) {
280 loop
->iter
= osl_util_read_string(NULL
, input
);
281 loop
->nb_stmts
= osl_util_read_int(NULL
, input
);
283 OSL_malloc(loop
->stmt_ids
, int *, loop
->nb_stmts
* sizeof(int));
284 for (i
= 0; i
< loop
->nb_stmts
; i
++)
285 loop
->stmt_ids
[i
] = osl_util_read_int(NULL
, input
);
287 loop
->private_vars
= osl_util_read_line(NULL
, input
);
288 if (!strcmp(loop
->private_vars
, "(null)")) {
289 free(loop
->private_vars
);
290 loop
->private_vars
=NULL
;
293 loop
->directive
= osl_util_read_int(NULL
, input
);
297 loop
->next
= osl_loop_malloc ();
306 /*+***************************************************************************
307 * Memory allocation/deallocation function *
308 *****************************************************************************/
312 * osl_loop_malloc function:
313 * this function allocates the memory space for an osl_loop_t
314 * structure and sets its fields with default values. Then it returns a
315 * pointer to the allocated space.
317 * \return A pointer to an empty loop structure with fields set to
320 osl_loop_p
osl_loop_malloc() {
323 OSL_malloc(loop
, osl_loop_p
, sizeof(osl_loop_t
));
326 loop
->stmt_ids
= NULL
;
327 loop
->private_vars
= NULL
;
336 * osl_loop_free function:
337 * this function frees the allocated memory for an loop structure.
339 * \param[in,out] loop The pointer to the loop structure we want to free.
341 void osl_loop_free(osl_loop_p loop
) {
343 while (loop
!= NULL
) {
344 osl_loop_p tmp
= loop
;
346 if (loop
->iter
) free(loop
->iter
);
347 if (loop
->stmt_ids
) free(loop
->stmt_ids
);
348 if (loop
->private_vars
) free(loop
->private_vars
);
357 /*+***************************************************************************
358 * Processing functions *
359 *****************************************************************************/
363 * osl_loop_clone_one function:
364 * this function builds and returns a "hard copy" (not a pointer copy) of
365 * "one" (and not the whole list) osl_loop_t data structure.
367 * \param[in] loop The pointer to the loop structure to clone.
368 * \return A pointer to the clone of the loop structure.
370 osl_loop_p
osl_loop_clone_one(osl_loop_p loop
) {
377 clone
= osl_loop_malloc();
378 OSL_strdup(clone
->iter
, loop
->iter
);
379 clone
->nb_stmts
= loop
->nb_stmts
;
380 OSL_malloc(clone
->stmt_ids
, int *, loop
->nb_stmts
* sizeof(int));
382 for (i
= 0; i
< loop
->nb_stmts
; i
++) {
383 clone
->stmt_ids
[i
] = loop
->stmt_ids
[i
];
386 clone
->directive
= loop
->directive
;
388 if(loop
->private_vars
!= NULL
)
389 OSL_strdup(clone
->private_vars
, loop
->private_vars
);
395 * osl_loop_clone function:
396 * this function builds and returns a "hard copy" (not a pointer copy) of a
397 * list of osl_loop_t data structures.
399 * \param[in] loop The pointer to the list of loop structure to clone.
400 * \return A pointer to the clone of list of the loop structure.
402 osl_loop_p
osl_loop_clone(osl_loop_p loop
) {
403 osl_loop_p clone
= NULL
;
404 osl_loop_p head
= NULL
;
412 head
= clone
= osl_loop_clone_one(loop
);
415 clone
->next
= osl_loop_clone_one(loop
);
426 * osl_loop_equal_one function:
427 * this function returns true if the two loop structures are the same
428 * (content-wise), false otherwise. This functions considers two loop
429 * structures as equal if the order of the array names differ, however
430 * the identifiers and names must be the same.
432 * \param[in] a1 The first loop structure.
433 * \param[in] a2 The second loop structure.
434 * \return 1 if a1 and a2 are the same (content-wise), 0 otherwise.
436 int osl_loop_equal_one(osl_loop_p a1
, osl_loop_p a2
) {
442 if (((a1
== NULL
) && (a2
!= NULL
)) || ((a1
!= NULL
) && (a2
== NULL
))) {
443 //OSL_info("loops are not the same (compare with NULL)");
447 // Check whether the number of names is the same.
448 if (a1
->nb_stmts
!= a2
->nb_stmts
) {
449 //OSL_info("loops are not the same (nb_stmts)");
453 if (strcmp(a1
->iter
, a2
->iter
)) {
454 //OSL_info("loops are not the same (iter name)");
457 // We accept a different order of the names, as long as the identifiers
459 for (i
= 0; i
< a1
->nb_stmts
; i
++) {
461 for (j
= 0; j
< a2
->nb_stmts
; j
++) {
462 if (a1
->stmt_ids
[i
] == a2
->stmt_ids
[j
]) {
468 //OSL_info("loop are not the same (stmt ids)");
473 //TODO: necessarily same ???
474 if (a1
->private_vars
!= a2
->private_vars
) { // NULL check
475 if (strcmp(a1
->private_vars
, a2
->private_vars
)) {
476 //OSL_info("loops are not the same (private vars)");
481 //TODO: necessarily same ???
482 if (a1
->directive
!= a2
->directive
) {
483 //OSL_info("loops are not the same (directive)");
491 * osl_loop_equal function:
492 * this function returns true if the two loop lists are the same
493 * (content-wise), false otherwise. Two lists are equal if one contains
494 * all the elements of the other and vice versa. The exact order of the
495 * nodes is not taken into account by this function.
497 * \param[in] a1 The first loop list.
498 * \param[in] a2 The second loop list.
499 * \return 1 if a1 and a2 are the same (content-wise), 0 otherwise.
501 int osl_loop_equal(osl_loop_p a1
, osl_loop_p a2
) {
507 if (((a1
== NULL
) && (a2
!= NULL
)) || ((a1
!= NULL
) && (a2
== NULL
))) {
508 OSL_info("lists of loops are not the same (compare with NULL)");
512 if (osl_loop_count(a1
) != osl_loop_count(a2
)) {
513 OSL_info("list of loops are not the same");
519 osl_loop_p temp
= a2
;
522 if(osl_loop_equal_one(a1
, temp
)==1){
530 OSL_info("list of loops are not the same");
541 * osl_loop_interface function:
542 * this function creates an interface structure corresponding to the loop
543 * extension and returns it.
545 * \return An interface structure for the loop extension.
547 osl_interface_p
osl_loop_interface() {
548 osl_interface_p interface
= osl_interface_malloc();
550 OSL_strdup(interface
->URI
, OSL_URI_LOOP
);
551 interface
->idump
= (osl_idump_f
)osl_loop_idump
;
552 interface
->sprint
= (osl_sprint_f
)osl_loop_sprint
;
553 interface
->sread
= (osl_sread_f
)osl_loop_sread
;
554 interface
->malloc
= (osl_malloc_f
)osl_loop_malloc
;
555 interface
->free
= (osl_free_f
)osl_loop_free
;
556 interface
->clone
= (osl_clone_f
)osl_loop_clone
;
557 interface
->equal
= (osl_equal_f
)osl_loop_equal
;
564 * osl_loop_add function:
565 * this function adds a loop structure at the end of the list
567 * \param[in,out] ll Pointer to a list of loops.
568 * \param[in] loop Pointer to the loop structure to be added.
570 void osl_loop_add(osl_loop_p loop
, osl_loop_p
*ll
) {
581 * this function returns the number of elements in the list
583 * \param[in] ll Pointer to a list of loops.
584 * \return Number of elements in the list
586 int osl_loop_count(osl_loop_p ll
) {