Clan  0.8.1
scop.c
Go to the documentation of this file.
1 
2  /*+------- <| --------------------------------------------------------**
3  ** A Clan **
4  **--- /.\ -----------------------------------------------------**
5  ** <| [""M# scop.c **
6  **- A | # -----------------------------------------------------**
7  ** /.\ [""M# First version: 30/04/2008 **
8  **- [""M# | # U"U#U -----------------------------------------------**
9  | # | # \ .:/
10  | # | #___| #
11  ****** | "--' .-" ******************************************************
12  * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) *
13  **** | # ## ###### *****************************************************
14  * \ .::::'/ *
15  * \ ::::'/ Copyright (C) 2008 University Paris-Sud 11 *
16  * :8a| # # ## *
17  * ::88a ### This is free software; you can redistribute it *
18  * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser *
19  * ::::::::888a88a[]::: General Public License as published by the Free *
20  *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the *
21  *::::::::8::::888:Y8888:: License, or (at your option) any later version. *
22  *::::':::88::::888::Y88a::::::::::::... *
23  *::'::.. . ..... .. ... . *
24  * This software is distributed in the hope that it will be useful, but *
25  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
26  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27  * for more details. *
28  * *
29  * You should have received a copy of the GNU Lesser General Public License *
30  * along with software; if not, write to the Free Software Foundation, Inc., *
31  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
32  * *
33  * Clan, the Chunky Loop Analyzer *
34  * Written by Cedric Bastoul, Cedric.Bastoul@u-psud.fr *
35  * *
36  ******************************************************************************/
37 
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <string.h>
43 
44 #include <osl/vector.h>
45 #include <osl/relation.h>
46 #include <osl/relation_list.h>
47 #include <osl/statement.h>
48 #include <osl/strings.h>
49 #include <osl/extensions/scatnames.h>
50 #include <osl/extensions/arrays.h>
51 #include <osl/extensions/coordinates.h>
52 #include <osl/extensions/clay.h>
53 #include <osl/extensions/extbody.h>
54 #include <osl/generic.h>
55 #include <osl/body.h>
56 #include <osl/scop.h>
57 #include <source/parser.h>
58 #include <clan/macros.h>
59 #include <clan/options.h>
60 #include <clan/relation.h>
61 #include <clan/statement.h>
62 #include <clan/scop.h>
63 
64 
65 extern int scanner_scop_start;
66 extern int scanner_scop_end;
67 extern int parser_indent;
68 
69 
70 /*+****************************************************************************
71  * Processing functions *
72  ******************************************************************************/
73 
74 osl_scop_p clan_parse(FILE*, clan_options_p);
75 
84 osl_scop_p clan_scop_extract(FILE* input, clan_options_p options) {
85  return clan_parse(input, options);
86 }
87 
88 
96 void clan_scop_compact(osl_scop_p scop) {
97  clan_statement_compact(scop->statement, osl_scop_get_nb_parameters(scop));
98 }
99 
100 
109 void clan_scop_print(FILE* file, osl_scop_p scop, clan_options_p options) {
110 
111  if ((scop != NULL) && (options->castle)) {
112  fprintf(file, "# \n");
113  fprintf(file, "# <| \n");
114  fprintf(file, "# A \n");
115  fprintf(file, "# /.\\ \n");
116  fprintf(file, "# <| [\"\"M# \n");
117  fprintf(file, "# A | # Clan McCloog Castle \n");
118  fprintf(file, "# /.\\ [\"\"M# [Generated by Clan ");
119  fprintf(file, "%s]\n", CLAN_VERSION);
120  fprintf(file, "# [\"\"M# | # U\"U#U \n");
121  fprintf(file, "# | # | # \\ .:/ \n");
122  fprintf(file, "# | # | #___| # \n");
123  fprintf(file, "# | \"--' .-\" \n");
124  fprintf(file, "# |\"-\"-\"-\"-\"-#-#-## \n");
125  fprintf(file, "# | # ## ###### \n");
126  fprintf(file, "# \\ .::::'/ \n");
127  fprintf(file, "# \\ ::::'/ \n");
128  fprintf(file, "# :8a| # # ## \n");
129  fprintf(file, "# ::88a ### \n");
130  fprintf(file, "# ::::888a 8a ##::. \n");
131  fprintf(file, "# ::::::888a88a[]:::: \n");
132  fprintf(file, "# :::::::::SUNDOGa8a::::. .. \n");
133  fprintf(file, "# :::::8::::888:Y8888:::::::::... \n");
134  fprintf(file, "#::':::88::::888::Y88a______________________________");
135  fprintf(file, "________________________\n");
136  fprintf(file, "#:: ::::88a::::88a:Y88a ");
137  fprintf(file, " __---__-- __\n");
138  fprintf(file, "#' .: ::Y88a:::::8a:Y88a ");
139  fprintf(file, "__----_-- -------_-__\n");
140  fprintf(file, "# :' ::::8P::::::::::88aa. _ _- -");
141  fprintf(file, "- --_ --- __ --- __--\n");
142  fprintf(file, "#.:: :::::::::::::::::::Y88as88a...s88aa.\n#\n");
143  }
144 
145  if (options->outscoplib)
146  osl_scop_print_scoplib(file, scop);
147  else
148  osl_scop_print(file, scop);
149 }
150 
151 
161 void clan_scop_generate_scatnames(osl_scop_p scop) {
162  osl_statement_p current, deepest;
163  osl_scatnames_p scatnames;
164  osl_strings_p iterators = NULL;
165  osl_strings_p names = NULL;
166  osl_generic_p extension;
167  osl_body_p body = NULL;
168  char buffer[CLAN_MAX_STRING];
169  int max_depth = -1;
170  int i;
171 
172  // Find the deepest statement to reuse its original iterators.
173  current = scop->statement;
174  while (current != NULL) {
175  if (current->domain->nb_output_dims > max_depth) {
176  max_depth = current->domain->nb_output_dims;
177  deepest = current;
178  body = (osl_body_p)osl_generic_lookup(deepest->extension, OSL_URI_BODY);
179  if (body)
180  iterators = body->iterators;
181  }
182  current = current->next;
183  }
184 
185  // It there are no scattering dimension, do nothing.
186  if (max_depth <= 0)
187  return;
188 
189  // Create the NULL-terminated list of scattering dimension names.
190  names = osl_strings_malloc();
191  for (i = 0; i < max_depth; i++) {
192  sprintf(buffer, "b%d", i);
193  osl_strings_add(names, buffer);
194  osl_strings_add(names, iterators->string[i]);
195  }
196  sprintf(buffer, "b%d", max_depth);
197  osl_strings_add(names, buffer);
198 
199  // Build the scatnames extension.
200  scatnames = osl_scatnames_malloc();
201  scatnames->names = names;
202 
203  // Build the generic extension and insert it to the extension list.
204  extension = osl_generic_malloc();
205  extension->interface = osl_scatnames_interface();
206  extension->data = scatnames;
207  osl_generic_add(&scop->extension, extension);
208 }
209 
210 
218 void clan_scop_generate_coordinates(osl_scop_p scop, char* name) {
219  osl_coordinates_p coordinates;
220  osl_generic_p extension;
221 
222  // Build the coordinates extension
223  coordinates = osl_coordinates_malloc();
224  CLAN_strdup(coordinates->name, name);
225  coordinates->line_start = scanner_scop_start + 1;
226  coordinates->line_end = scanner_scop_end;
227  coordinates->column_start = 0;
228  coordinates->column_end = 0;
229  coordinates->indent = (parser_indent != CLAN_UNDEFINED) ? parser_indent : 0;
230 
231  // Build the generic extension and insert it to the extension list.
232  extension = osl_generic_malloc();
233  extension->interface = osl_coordinates_interface();
234  extension->data = coordinates;
235  osl_generic_add(&scop->extension, extension);
236 }
237 
238 
246 void clan_scop_generate_clay(osl_scop_p scop, char* script) {
247  osl_clay_p clay;
248  osl_generic_p extension;
249 
250  if ((script != NULL) && (strlen(script) > 0)) {
251  // Build the clay extension
252  clay = osl_clay_malloc();
253  CLAN_strdup(clay->script, script);
254 
255  // Build the generic extension and insert it to the extension list.
256  extension = osl_generic_malloc();
257  extension->interface = osl_clay_interface();
258  extension->data = clay;
259  osl_generic_add(&scop->extension, extension);
260  }
261 }
262 
263 
276 void clan_scop_update_coordinates(osl_scop_p scop,
277  int coordinates[5][CLAN_MAX_SCOPS]) {
278  int i = 0;
279  osl_coordinates_p old;
280 
281  while (scop != NULL) {
282  if (i > CLAN_MAX_SCOPS)
283  CLAN_error("too many SCoPs! Change CLAN_MAX_SCOPS and recompile Clan.");
284 
285  old = osl_generic_lookup(scop->extension, OSL_URI_COORDINATES);
286  if (old == NULL)
287  CLAN_error("coordinates extension not present");
288  // When columns are at 0, it means the scop has not been autodetected.
289  // - The line starts at +1 (after the pragma scop) if no autodetection,
290  // - The column stops at -1 (previous read char) if autodetection.
291  old->line_start = coordinates[0][i] + ((coordinates[2][i] == 0)? 1 : 0);
292  old->line_end = coordinates[1][i];
293  old->column_start = coordinates[2][i];
294  old->column_end = coordinates[3][i] - ((coordinates[3][i] > 0)? 1 : 0);
295  i++;
296  scop = scop->next;
297  }
298 }
299 
300 
313 void clan_scop_print_autopragma(FILE* input, int nb_scops,
314  int coordinates[5][CLAN_MAX_SCOPS]) {
315  int i, j, line, column;
316  char c;
317  FILE* autopragma;
318 
319  if (CLAN_DEBUG) {
320  CLAN_debug("coordinates:");
321  for (i = 0; i < 5; i++) {
322  for (j = 0; j < nb_scops; j++)
323  printf("%3d ", coordinates[i][j]);
324  printf("\n");
325  }
326  }
327 
328  if ((autopragma = fopen(CLAN_AUTOPRAGMA_FILE, "w")) == NULL)
329  CLAN_error("cannot create the autopragma file");
330  line = 1;
331  column = 1;
332  i = 0;
333  while ((c = fgetc(input)) != EOF) {
334  if (nb_scops > 0) {
335  if ((line == coordinates[0][i]) && (column == coordinates[2][i])) {
336  fprintf(autopragma, "\n#pragma scop\n");
337  for (j = 0; j < coordinates[2][i] - 1; j++)
338  fprintf(autopragma, " ");
339  }
340  if ((line == coordinates[1][i]) && (column == coordinates[3][i])) {
341  fprintf(autopragma, "\n#pragma endscop\n");
342  for (j = 0; j < coordinates[3][i] - 1; j++)
343  fprintf(autopragma, " ");
344  if (i < nb_scops - 1) {
345  do
346  i++;
347  while ((i < nb_scops - 1) && !coordinates[4][i]);
348  }
349  }
350  }
351  fputc(c, autopragma);
352  column++;
353  if (c == '\n') {
354  line++;
355  column = 1;
356  }
357  }
358  fclose(autopragma);
359 }
360 
361 
371 static
372 int clan_scop_no_pragma(char * filename, int line_start) {
373  int lines = 0;
374  int read = 1;
375  char c;
376  FILE* file;
377  char s1[CLAN_MAX_STRING];
378  char s2[CLAN_MAX_STRING];
379 
380  if (line_start < 0)
381  CLAN_error("negative line number");
382 
383  if (!(file = fopen(filename, "r")))
384  CLAN_error("unable to read the file");
385 
386  // Go to line_start in the file.
387  while ((lines < line_start - 1) && (read != EOF)) {
388  read = fscanf(file, "%c", &c);
389  if (read != EOF) {
390  if (c == '\n')
391  lines ++;
392  }
393  }
394 
395  if (lines != line_start - 1) {
396  fclose(file);
397  CLAN_error("not enough lines in the file");
398  }
399 
400  if (fscanf(file, " %s %s", s1, s2) != 2) {
401  fclose(file);
402  CLAN_debug("pragma not found: cannot read the two chains");
403  return CLAN_TRUE;
404  }
405 
406  fclose(file);
407  if (strcmp(s1, "#pragma") || strcmp(s2, "scop")) {
408  CLAN_debug("pragma not found: do not match \"#pragma scop\"");
409  return CLAN_TRUE;
410  }
411 
412  CLAN_debug("pragma found");
413  return CLAN_FALSE;
414 }
415 
416 
427 void clan_scop_insert_pragmas(osl_scop_p scop, char* filename, int test) {
428  int i, j, n = 0;
429  int infos[5][CLAN_MAX_SCOPS];
430  int tmp[5];
431  osl_coordinates_p coordinates;
432  FILE* input, *output;
433  size_t size;
434  char buffer[BUFSIZ];
435 
436  // Get coordinate information from the list of SCoPS.
437  while (scop != NULL) {
438  coordinates = osl_generic_lookup(scop->extension, OSL_URI_COORDINATES);
439  infos[0][n] = coordinates->line_start;
440  infos[1][n] = coordinates->line_end;
441  infos[2][n] = coordinates->column_start;
442  infos[3][n] = coordinates->column_end + 1;
443  infos[4][n] = clan_scop_no_pragma(filename, coordinates->line_start);
444  n++;
445  scop = scop->next;
446  }
447 
448  // Dirty and inefficient bubble sort to ensure the SCoP ordering is correct
449  // (this is ensured in Clan, but not if it is called from outside...).
450  for (i = n - 2; i >= 0; i--) {
451  for (j = 0; j <= i; j++) {
452  if (infos[0][j] > infos[0][j+1]) {
453  tmp[0]=infos[0][j]; infos[0][j]=infos[0][j+1]; infos[0][j+1]=tmp[0];
454  tmp[1]=infos[1][j]; infos[1][j]=infos[1][j+1]; infos[1][j+1]=tmp[1];
455  tmp[2]=infos[2][j]; infos[2][j]=infos[2][j+1]; infos[2][j+1]=tmp[2];
456  tmp[3]=infos[3][j]; infos[3][j]=infos[3][j+1]; infos[3][j+1]=tmp[3];
457  tmp[4]=infos[4][j]; infos[4][j]=infos[4][j+1]; infos[4][j+1]=tmp[4];
458  }
459  }
460  }
461 
462  // Quick check that there is no scop interleaving.
463  for (i = 0; i < n - 1; i++)
464  if (infos[1][i] > infos[0][i+1])
465  CLAN_error("SCoP interleaving");
466 
467  // Generate the temporary file with the pragma inserted.
468  if (!(input = fopen(filename, "r")))
469  CLAN_error("unable to read the input file");
470  clan_scop_print_autopragma(input, n, infos);
471  fclose(input);
472 
473  // Replace the original file, or keep the temporary file.
474  if (!test) {
475  if (!(input = fopen(CLAN_AUTOPRAGMA_FILE, "rb")))
476  CLAN_error("unable to read the temporary file");
477 
478  if (!(output = fopen(filename, "wb")))
479  CLAN_error("unable to write the output file");
480 
481  while ((size = fread(buffer, 1, BUFSIZ, input))) {
482  fwrite(buffer, 1, size, output);
483  }
484 
485  fclose(input);
486  fclose(output);
487 
488  if (remove(CLAN_AUTOPRAGMA_FILE) == -1)
489  CLAN_warning("unable to remove the temporary file");
490  }
491 }
492 
493 
499 void clan_scop_simplify(osl_scop_p scop) {
500  osl_statement_p statement;
501 
502  while (scop != NULL) {
503  statement = scop->statement;
504  while (statement != NULL) {
505  clan_relation_simplify(statement->domain);
506  statement = statement->next;
507  }
508  scop = scop->next;
509  }
510 }
void clan_scop_print(FILE *file, osl_scop_p scop, clan_options_p options)
Definition: scop.c:109
int castle
Definition: options.h:57
void clan_scop_generate_coordinates(osl_scop_p scop, char *name)
Definition: scop.c:218
osl_scop_p clan_scop_extract(FILE *input, clan_options_p options)
Definition: scop.c:84
int outscoplib
Definition: options.h:70
void clan_scop_simplify(osl_scop_p scop)
Definition: scop.c:499
osl_scop_p clan_parse(FILE *, clan_options_p)
int parser_indent
void clan_scop_print_autopragma(FILE *input, int nb_scops, int coordinates[5][CLAN_MAX_SCOPS])
Definition: scop.c:313
void clan_scop_generate_clay(osl_scop_p scop, char *script)
Definition: scop.c:246
int scanner_scop_start
void clan_statement_compact(osl_statement_p statement, int nb_parameters)
Definition: statement.c:62
void clan_scop_generate_scatnames(osl_scop_p scop)
Definition: scop.c:161
void clan_scop_update_coordinates(osl_scop_p scop, int coordinates[5][CLAN_MAX_SCOPS])
Definition: scop.c:276
void clan_scop_compact(osl_scop_p scop)
Definition: scop.c:96
void clan_scop_insert_pragmas(osl_scop_p scop, char *filename, int test)
Definition: scop.c:427
void clan_relation_simplify(osl_relation_p relation)
Definition: relation.c:1054
int scanner_scop_end
static int clan_scop_no_pragma(char *filename, int line_start)
Definition: scop.c:372