OpenScop  0.9.1
loop.c
Go to the documentation of this file.
1 
2  /*+-----------------------------------------------------------------**
3  ** OpenScop Library **
4  **-----------------------------------------------------------------**
5  ** extensions/loop.c **
6  **-----------------------------------------------------------------**
7  ** First version: 03/06/2013 **
8  **-----------------------------------------------------------------**
9 
10 
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  * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
29  * *
30  * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
31  * *
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 *
35  * are met: *
36  * *
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. *
44  * *
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. *
55  * *
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> *
60  * *
61  *****************************************************************************/
62 
63 #include <stdlib.h>
64 #include <stdio.h>
65 #include <string.h>
66 #include <ctype.h>
67 
68 #include <osl/macros.h>
69 #include <osl/util.h>
70 #include <osl/strings.h>
71 #include <osl/interface.h>
72 #include <osl/extensions/loop.h>
73 
74 
75 /*+***************************************************************************
76  * Structure display function *
77  *****************************************************************************/
78 
79 
91 void osl_loop_idump(FILE * file, osl_loop_p loop, int level) {
92  int j, first = 1, number=1;
93  size_t i;
94 
95  // Go to the right level.
96  for (j = 0; j < level; j++)
97  fprintf(file, "|\t");
98 
99  if (loop != NULL)
100  fprintf(file, "+-- osl_loop_t\n");
101  else
102  fprintf(file, "+-- NULL loop\n");
103 
104  while (loop != NULL) {
105  // Go to the right level.
106  if (!first) {
107  // Go to the right level.
108  for (j = 0; j < level; j++)
109  fprintf(file, "|\t");
110 
111  fprintf(file, "| osl_loop_t (node %d)\n", number);
112  } else {
113  first = 0;
114  }
115 
116  // A blank line.
117  for (j = 0; j <= level+1; j++)
118  fprintf(file, "|\t");
119  fprintf(file, "\n");
120 
121  // Display the number of names.
122  for (j = 0; j <= level; j++)
123  fprintf(file, "|\t");
124  fprintf(file, "+--iterator: %s\n", loop->iter);
125 
126  for (j = 0; j <= level; j++)
127  fprintf(file, "|\t");
128  fprintf(file, "+--nb_stmts: %zu\n", loop->nb_stmts);
129 
130  // Display the id/name.
131  for (j = 0; j <= level; j++)
132  fprintf(file, "|\t");
133  fprintf(file, "+--stmt_ids:");
134  for(i = 0; i < loop->nb_stmts; i++) {
135  // Go to the right level.
136  fprintf(file, "%2d, ", loop->stmt_ids[i]);
137  }
138  fprintf(file, "\n");
139 
140 
141  for (j = 0; j <= level; j++)
142  fprintf(file, "|\t");
143  fprintf(file, "+--private_vars: %s\n", loop->private_vars);
144 
145  for (j = 0; j <= level; j++)
146  fprintf(file, "|\t");
147  fprintf(file, "+--directive: %d\n", loop->directive);
148 
149  for (j = 0; j <= level; j++)
150  fprintf(file, "|\t");
151  fprintf(file, "+--user: %s\n", loop->user);
152 
153  loop = loop->next;
154  number++;
155 
156  // Next line.
157  if (loop != NULL) {
158  for (j = 0; j <= level; j++)
159  fprintf(file, "|\t");
160  fprintf(file, "V\n");
161  }
162  }
163 
164  // The last line.
165  for (j = 0; j <= level; j++)
166  fprintf(file, "|\t");
167  fprintf(file, "\n");
168 }
169 
170 
179 void osl_loop_dump(FILE * file, osl_loop_p loop) {
180  osl_loop_idump(file, loop, 0);
181 }
182 
183 
192  size_t i;
193  int nloop = 0;
194  size_t high_water_mark = OSL_MAX_STRING;
195  char *string = NULL;
196  char buffer[OSL_MAX_STRING];
197 
198  OSL_malloc(string, char *, high_water_mark * sizeof(char));
199  string[0] = '\0';
200 
201  sprintf(buffer, "# Number of loops\n%d\n",osl_loop_count(loop));
202  osl_util_safe_strcat(&string, buffer, &high_water_mark);
203 
204  while (loop != NULL) {
205  sprintf(buffer, "# ===========================================\n");
206  osl_util_safe_strcat(&string, buffer, &high_water_mark);
207 
208  sprintf(buffer, "# Loop number %d \n", ++nloop);
209  osl_util_safe_strcat(&string, buffer, &high_water_mark);
210 
211  sprintf(buffer, "# Iterator name\n");
212  osl_util_safe_strcat(&string, buffer, &high_water_mark);
213  sprintf(buffer, "%s\n", loop->iter);
214  osl_util_safe_strcat(&string, buffer, &high_water_mark);
215 
216  sprintf(buffer, "# Number of stmts\n");
217  osl_util_safe_strcat(&string, buffer, &high_water_mark);
218  sprintf(buffer, "%zu\n", loop->nb_stmts);
219  osl_util_safe_strcat(&string, buffer, &high_water_mark);
220 
221  if (loop->nb_stmts) {
222  sprintf(buffer, "# Statement identifiers\n");
223  osl_util_safe_strcat(&string, buffer, &high_water_mark);
224  }
225  for (i = 0; i < loop->nb_stmts; i++) {
226  sprintf(buffer, "%d\n", loop->stmt_ids[i]);
227  osl_util_safe_strcat(&string, buffer, &high_water_mark);
228  }
229 
230  sprintf(buffer, "# Private variables\n");
231  osl_util_safe_strcat(&string, buffer, &high_water_mark);
232  sprintf(buffer, "%s\n", loop->private_vars);
233  osl_util_safe_strcat(&string, buffer, &high_water_mark);
234 
235  sprintf(buffer, "# Directive\n");
236  osl_util_safe_strcat(&string, buffer, &high_water_mark);
237  sprintf(buffer, "%d", loop->directive);
238  osl_util_safe_strcat(&string, buffer, &high_water_mark);
239 
240  // special case for OSL_LOOP_DIRECTIVE_USER
241  if (loop->directive == OSL_LOOP_DIRECTIVE_USER) {
242  sprintf(buffer, " %s", loop->user);
243  osl_util_safe_strcat(&string, buffer, &high_water_mark);
244  }
245  sprintf(buffer, "\n");
246  osl_util_safe_strcat(&string, buffer, &high_water_mark);
247 
248  loop = loop->next;
249  }
250 
251  OSL_realloc(string, char *, (strlen(string) + 1) * sizeof(char));
252  return string;
253 }
254 
255 
256 /*****************************************************************************
257  * Reading function *
258  *****************************************************************************/
259 
260 
272 osl_loop_p osl_loop_sread(char **input) {
273  size_t i;
274  int nb_loops;
275  osl_loop_p head;
276  osl_loop_p loop;
277 
278  if (input == NULL) {
279  OSL_debug("no loop optional tag");
280  return NULL;
281  }
282 
283  // Find the number of names provided.
284  nb_loops = osl_util_read_int(NULL, input);
285  if(nb_loops == 0)
286  return NULL;
287 
288  // Allocate the array of id and names.
289  head = loop = osl_loop_malloc();
290 
291  while (nb_loops != 0) {
292 
293  loop->iter = osl_util_read_string(NULL, input);
294  loop->nb_stmts = (size_t)osl_util_read_int(NULL, input);
295 
296  OSL_malloc(loop->stmt_ids, int *, loop->nb_stmts * sizeof(int));
297  for (i = 0; i < loop->nb_stmts; i++)
298  loop->stmt_ids[i] = osl_util_read_int(NULL, input);
299 
300  loop->private_vars = osl_util_read_line(NULL, input);
301  if (!strcmp(loop->private_vars, "(null)")) {
302  free(loop->private_vars);
303  loop->private_vars=NULL;
304  }
305 
306  loop->directive = osl_util_read_int(NULL, input);
307 
308  // special case for OSL_LOOP_DIRECTIVE_USER
309  if (loop->directive == OSL_LOOP_DIRECTIVE_USER) {
310  loop->user = osl_util_read_line(NULL, input);
311  if (!strcmp(loop->user, "(null)")) {
312  free(loop->user);
313  loop->user=NULL;
314  }
315  }
316 
317  nb_loops--;
318  if (nb_loops != 0) {
319  loop->next = osl_loop_malloc ();
320  loop = loop->next;
321  }
322  }
323 
324  return head;
325 }
326 
327 
328 /*+***************************************************************************
329  * Memory allocation/deallocation function *
330  *****************************************************************************/
331 
332 
343  osl_loop_p loop;
344 
345  OSL_malloc(loop, osl_loop_p, sizeof(osl_loop_t));
346  loop->iter = NULL;
347  loop->nb_stmts = 0;
348  loop->stmt_ids = NULL;
349  loop->private_vars = NULL;
350  loop->directive = 0;
351  loop->user = NULL;
352  loop->next = NULL;
353 
354  return loop;
355 }
356 
357 
365 
366  while (loop != NULL) {
367  osl_loop_p tmp = loop;
368 
369  if (loop->iter) free(loop->iter);
370  if (loop->stmt_ids) free(loop->stmt_ids);
371  if (loop->private_vars) free(loop->private_vars);
372  if (loop->user) free(loop->user);
373 
374  loop = loop->next;
375 
376  free(tmp);
377  }
378 }
379 
380 
381 /*+***************************************************************************
382  * Processing functions *
383  *****************************************************************************/
384 
385 
395  size_t i;
396  osl_loop_p clone;
397 
398  if (loop == NULL)
399  return NULL;
400 
401  clone = osl_loop_malloc();
402  OSL_strdup(clone->iter, loop->iter);
403  clone->nb_stmts = loop->nb_stmts;
404  OSL_malloc(clone->stmt_ids, int *, loop->nb_stmts * sizeof(int));
405 
406  for (i = 0; i < loop->nb_stmts; i++) {
407  clone->stmt_ids[i] = loop->stmt_ids[i];
408  }
409 
410  clone->directive = loop->directive;
411 
412  if(loop->private_vars != NULL)
413  OSL_strdup(clone->private_vars, loop->private_vars);
414 
415  if(loop->user != NULL)
416  OSL_strdup(clone->user, loop->user);
417 
418  return clone;
419 }
420 
430  osl_loop_p clone = NULL;
431  osl_loop_p head = NULL;
432 
433  if (loop == NULL)
434  return NULL;
435 
436  while (loop) {
437 
438  if (clone==NULL) {
439  head = clone = osl_loop_clone_one(loop);
440  }
441  else {
442  clone->next = osl_loop_clone_one(loop);
443  clone = clone->next;
444  }
445 
446  loop = loop->next;
447  }
448 
449  return head;
450 }
451 
464  size_t i, j, found;
465 
466  if (a1 == a2)
467  return 1;
468 
469  if (((a1 == NULL) && (a2 != NULL)) || ((a1 != NULL) && (a2 == NULL))) {
470  //OSL_info("loops are not the same (compare with NULL)");
471  return 0;
472  }
473 
474  // Check whether the number of names is the same.
475  if (a1->nb_stmts != a2->nb_stmts) {
476  //OSL_info("loops are not the same (nb_stmts)");
477  return 0;
478  }
479 
480  if (strcmp(a1->iter, a2->iter)) {
481  //OSL_info("loops are not the same (iter name)");
482  return 0;
483  }
484  // We accept a different order of the names, as long as the identifiers
485  // are the same.
486  for (i = 0; i < a1->nb_stmts; i++) {
487  found = 0;
488  for (j = 0; j < a2->nb_stmts; j++) {
489  if (a1->stmt_ids[i] == a2->stmt_ids[j]) {
490  found = 1;
491  break;
492  }
493  }
494  if (found != 1) {
495  //OSL_info("loop are not the same (stmt ids)");
496  return 0;
497  }
498  }
499 
500  //TODO: necessarily same ???
501  if (a1->private_vars != a2->private_vars) { // NULL check
502  if (strcmp(a1->private_vars, a2->private_vars)) {
503  //OSL_info("loops are not the same (private vars)");
504  return 0;
505  }
506  }
507 
508  //TODO: necessarily same ???
509  if (a1->directive != a2->directive) {
510  //OSL_info("loops are not the same (directive)");
511  return 0;
512  }
513 
514  if (a1->user != a2->user) { // NULL check
515  if (strcmp(a1->user, a2->user)) {
516  return 0;
517  }
518  }
519 
520  return 1;
521 }
522 
535  int found = 0;
536 
537  if (a1 == a2)
538  return 1;
539 
540  if (((a1 == NULL) && (a2 != NULL)) || ((a1 != NULL) && (a2 == NULL))) {
541  OSL_info("lists of loops are not the same (compare with NULL)");
542  return 0;
543  }
544 
545  if (osl_loop_count(a1) != osl_loop_count(a2)) {
546  OSL_info("list of loops are not the same");
547  return 0;
548  }
549 
550  while (a1) {
551  found = 0;
552  osl_loop_p temp = a2;
553 
554  while (temp) {
555  if(osl_loop_equal_one(a1, temp)==1){
556  found= 1;
557  break;
558  }
559  temp = temp->next;
560  }
561 
562  if(found!=1){
563  OSL_info("list of loops are not the same");
564  return 0;
565  }
566  a1 = a1->next;
567  }
568 
569  return 1;
570 }
571 
572 
582 
583  OSL_strdup(interface->URI, OSL_URI_LOOP);
584  interface->idump = (osl_idump_f)osl_loop_idump;
585  interface->sprint = (osl_sprint_f)osl_loop_sprint;
586  interface->sread = (osl_sread_f)osl_loop_sread;
587  interface->malloc = (osl_malloc_f)osl_loop_malloc;
588  interface->free = (osl_free_f)osl_loop_free;
589  interface->clone = (osl_clone_f)osl_loop_clone;
590  interface->equal = (osl_equal_f)osl_loop_equal;
591 
592  return interface;
593 }
594 
595 
604 
605  while (*ll != NULL)
606  ll = &(*ll)->next;
607 
608  *ll = loop;
609 }
610 
611 
620  int count = 0;
621  while (ll) {
622  count++;
623  ll = ll->next;
624  }
625 
626  return count;
627 }
int * stmt_ids
Array of statement identifiers.
Definition: loop.h:98
int directive
Loop directive to implement.
Definition: loop.h:100
osl_loop_p osl_loop_clone(osl_loop_p loop)
Definition: loop.c:429
int osl_loop_equal_one(osl_loop_p a1, osl_loop_p a2)
Definition: loop.c:463
void *(* osl_clone_f)(void *)
Definition: interface.h:80
void *(* osl_sread_f)(char **)
Definition: interface.h:77
int osl_util_read_int(FILE *file, char **str)
Definition: util.c:140
size_t nb_stmts
Number of statements in the loop.
Definition: loop.h:97
void(* osl_idump_f)(FILE *, void *, int)
Definition: interface.h:75
#define OSL_LOOP_DIRECTIVE_USER
Definition: loop.h:84
osl_interface_p osl_interface_malloc(void)
Definition: interface.c:212
#define OSL_info(msg)
Definition: macros.h:139
int osl_loop_equal(osl_loop_p a1, osl_loop_p a2)
Definition: loop.c:534
char * osl_loop_sprint(osl_loop_p loop)
Definition: loop.c:191
char * private_vars
\0 terminated variable names
Definition: loop.h:99
void osl_util_safe_strcat(char **dst, char *src, size_t *hwm)
Definition: util.c:482
char *(* osl_sprint_f)(void *)
Definition: interface.h:76
char * iter
\0 terminated iterator name
Definition: loop.h:96
void osl_loop_dump(FILE *file, osl_loop_p loop)
Definition: loop.c:179
#define OSL_debug(msg)
Definition: macros.h:133
osl_loop_p osl_loop_malloc(void)
Definition: loop.c:342
#define OSL_strdup(destination, source)
Definition: macros.h:169
void *(* osl_malloc_f)(void)
Definition: interface.h:78
osl_interface_p osl_loop_interface(void)
Definition: loop.c:580
char * osl_util_read_string(FILE *file, char **str)
Definition: util.c:181
#define OSL_realloc(ptr, type, size)
Definition: macros.h:163
osl_loop_p osl_loop_clone_one(osl_loop_p loop)
Definition: loop.c:394
Definition: loop.h:95
void osl_loop_idump(FILE *file, osl_loop_p loop, int level)
Definition: loop.c:91
int(* osl_equal_f)(void *, void *)
Definition: interface.h:81
void osl_loop_free(osl_loop_p loop)
Definition: loop.c:364
struct osl_loop * next
Definition: loop.h:102
#define OSL_MAX_STRING
Definition: macros.h:94
#define OSL_URI_LOOP
Definition: loop.h:77
void(* osl_free_f)(void *)
Definition: interface.h:79
char * user
\0 terminated user string
Definition: loop.h:101
osl_loop_p osl_loop_sread(char **input)
Definition: loop.c:272
int osl_loop_count(osl_loop_p ll)
Definition: loop.c:619
void osl_loop_add(osl_loop_p loop, osl_loop_p *ll)
Definition: loop.c:603
char * osl_util_read_line(FILE *file, char **str)
Definition: util.c:226
#define OSL_malloc(ptr, type, size)
Definition: macros.h:157