1 2 /**-------------------------------------------------------------------** 3 ** CLooG ** 4 **-------------------------------------------------------------------** 5 ** pprint.c ** 6 **-------------------------------------------------------------------** 7 ** First version: october 26th 2001 ** 8 **-------------------------------------------------------------------**/ 9 10 11/****************************************************************************** 12 * CLooG : the Chunky Loop Generator (experimental) * 13 ****************************************************************************** 14 * * 15 * Copyright (C) 2001-2005 Cedric Bastoul * 16 * * 17 * This library is free software; you can redistribute it and/or * 18 * modify it under the terms of the GNU Lesser General Public * 19 * License as published by the Free Software Foundation; either * 20 * version 2.1 of the License, or (at your option) any later version. * 21 * * 22 * This library is distributed in the hope that it will be useful, * 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 25 * Lesser General Public License for more details. * 26 * * 27 * You should have received a copy of the GNU Lesser General Public * 28 * License along with this library; if not, write to the Free Software * 29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 30 * Boston, MA 02110-1301 USA * 31 * * 32 * CLooG, the Chunky Loop Generator * 33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * 34 * * 35 ******************************************************************************/ 36/* CAUTION: the english used for comments is probably the worst you ever read, 37 * please feel free to correct and improve it ! 38 */ 39 40/* June 22nd 2005: General adaptation for GMP. 41 * October 26th 2005: General adaptation from CloogDomain to Matrix data 42 * structure for all constraint systems. 43 * October 27th 2005: General adaptation from CloogEqual to Matrix data 44 * structure for equality spreading. 45 */ 46 47# include <stdlib.h> 48# include <stdio.h> 49# include <string.h> 50#include <assert.h> 51# include "../include/cloog/cloog.h" 52 53#ifdef OSL_SUPPORT 54#include <osl/util.h> 55#include <osl/body.h> 56#include <osl/statement.h> 57#include <osl/scop.h> 58#endif 59 60 61static void pprint_name(FILE *dst, struct clast_name *n); 62static void pprint_term(struct cloogoptions *i, FILE *dst, struct clast_term *t); 63static void pprint_sum(struct cloogoptions *opt, 64 FILE *dst, struct clast_reduction *r); 65static void pprint_binary(struct cloogoptions *i, 66 FILE *dst, struct clast_binary *b); 67static void pprint_minmax_f(struct cloogoptions *info, 68 FILE *dst, struct clast_reduction *r); 69static void pprint_minmax_c(struct cloogoptions *info, 70 FILE *dst, struct clast_reduction *r); 71static void pprint_reduction(struct cloogoptions *i, 72 FILE *dst, struct clast_reduction *r); 73static void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e); 74static void pprint_equation(struct cloogoptions *i, 75 FILE *dst, struct clast_equation *eq); 76static void pprint_assignment(struct cloogoptions *i, FILE *dst, 77 struct clast_assignment *a); 78static void pprint_user_stmt(struct cloogoptions *options, FILE *dst, 79 struct clast_user_stmt *u); 80static void pprint_guard(struct cloogoptions *options, FILE *dst, int indent, 81 struct clast_guard *g); 82static void pprint_for(struct cloogoptions *options, FILE *dst, int indent, 83 struct clast_for *f); 84static void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent, 85 struct clast_stmt *s); 86 87 88void pprint_name(FILE *dst, struct clast_name *n) 89{ 90 fprintf(dst, "%s", n->name); 91} 92 93/** 94 * This function returns a string containing the printing of a value (possibly 95 * an iterator or a parameter with its coefficient or a constant). 96 * - val is the coefficient or constant value, 97 * - name is a string containing the name of the iterator or of the parameter, 98 */ 99void pprint_term(struct cloogoptions *i, FILE *dst, struct clast_term *t) 100{ 101 if (t->var) { 102 int group = t->var->type == clast_expr_red && 103 ((struct clast_reduction*) t->var)->n > 1; 104 if (cloog_int_is_one(t->val)) 105 ; 106 else if (cloog_int_is_neg_one(t->val)) 107 fprintf(dst, "-"); 108 else { 109 cloog_int_print(dst, t->val); 110 fprintf(dst, "*"); 111 } 112 if (group) 113 fprintf(dst, "("); 114 pprint_expr(i, dst, t->var); 115 if (group) 116 fprintf(dst, ")"); 117 } else 118 cloog_int_print(dst, t->val); 119} 120 121void pprint_sum(struct cloogoptions *opt, FILE *dst, struct clast_reduction *r) 122{ 123 int i; 124 struct clast_term *t; 125 126 assert(r->n >= 1); 127 assert(r->elts[0]->type == clast_expr_term); 128 t = (struct clast_term *) r->elts[0]; 129 pprint_term(opt, dst, t); 130 131 for (i = 1; i < r->n; ++i) { 132 assert(r->elts[i]->type == clast_expr_term); 133 t = (struct clast_term *) r->elts[i]; 134 if (cloog_int_is_pos(t->val)) 135 fprintf(dst, "+"); 136 pprint_term(opt, dst, t); 137 } 138} 139 140void pprint_binary(struct cloogoptions *i, FILE *dst, struct clast_binary *b) 141{ 142 const char *s1 = NULL, *s2 = NULL, *s3 = NULL; 143 int group = b->LHS->type == clast_expr_red && 144 ((struct clast_reduction*) b->LHS)->n > 1; 145 if (i->language == CLOOG_LANGUAGE_FORTRAN) { 146 switch (b->type) { 147 case clast_bin_fdiv: 148 s1 = "FLOOR(REAL(", s2 = ")/REAL(", s3 = "))"; 149 break; 150 case clast_bin_cdiv: 151 s1 = "CEILING(REAL(", s2 = ")/REAL(", s3 = "))"; 152 break; 153 case clast_bin_div: 154 if (group) 155 s1 = "(", s2 = ")/", s3 = ""; 156 else 157 s1 = "", s2 = "/", s3 = ""; 158 break; 159 case clast_bin_mod: 160 s1 = "MOD(", s2 = ", ", s3 = ")"; 161 break; 162 } 163 } else { 164 switch (b->type) { 165 case clast_bin_fdiv: 166 s1 = "floord(", s2 = ",", s3 = ")"; 167 break; 168 case clast_bin_cdiv: 169 s1 = "ceild(", s2 = ",", s3 = ")"; 170 break; 171 case clast_bin_div: 172 if (group) 173 s1 = "(", s2 = ")/", s3 = ""; 174 else 175 s1 = "", s2 = "/", s3 = ""; 176 break; 177 case clast_bin_mod: 178 if (group) 179 s1 = "(", s2 = ")%", s3 = ""; 180 else 181 s1 = "", s2 = "%", s3 = ""; 182 break; 183 } 184 } 185 fprintf(dst, "%s", s1); 186 pprint_expr(i, dst, b->LHS); 187 fprintf(dst, "%s", s2); 188 cloog_int_print(dst, b->RHS); 189 fprintf(dst, "%s", s3); 190} 191 192void pprint_minmax_f(struct cloogoptions *info, FILE *dst, struct clast_reduction *r) 193{ 194 int i; 195 if (r->n == 0) 196 return; 197 fprintf(dst, r->type == clast_red_max ? "MAX(" : "MIN("); 198 pprint_expr(info, dst, r->elts[0]); 199 for (i = 1; i < r->n; ++i) { 200 fprintf(dst, ","); 201 pprint_expr(info, dst, r->elts[i]); 202 } 203 fprintf(dst, ")"); 204} 205 206void pprint_minmax_c(struct cloogoptions *info, FILE *dst, struct clast_reduction *r) 207{ 208 int i; 209 for (i = 1; i < r->n; ++i) 210 fprintf(dst, r->type == clast_red_max ? "max(" : "min("); 211 if (r->n > 0) 212 pprint_expr(info, dst, r->elts[0]); 213 for (i = 1; i < r->n; ++i) { 214 fprintf(dst, ","); 215 pprint_expr(info, dst, r->elts[i]); 216 fprintf(dst, ")"); 217 } 218} 219 220void pprint_reduction(struct cloogoptions *i, FILE *dst, struct clast_reduction *r) 221{ 222 switch (r->type) { 223 case clast_red_sum: 224 pprint_sum(i, dst, r); 225 break; 226 case clast_red_min: 227 case clast_red_max: 228 if (r->n == 1) { 229 pprint_expr(i, dst, r->elts[0]); 230 break; 231 } 232 if (i->language == CLOOG_LANGUAGE_FORTRAN) 233 pprint_minmax_f(i, dst, r); 234 else 235 pprint_minmax_c(i, dst, r); 236 break; 237 default: 238 assert(0); 239 } 240} 241 242void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e) 243{ 244 if (!e) 245 return; 246 switch (e->type) { 247 case clast_expr_name: 248 pprint_name(dst, (struct clast_name*) e); 249 break; 250 case clast_expr_term: 251 pprint_term(i, dst, (struct clast_term*) e); 252 break; 253 case clast_expr_red: 254 pprint_reduction(i, dst, (struct clast_reduction*) e); 255 break; 256 case clast_expr_bin: 257 pprint_binary(i, dst, (struct clast_binary*) e); 258 break; 259 default: 260 assert(0); 261 } 262} 263 264void pprint_equation(struct cloogoptions *i, FILE *dst, struct clast_equation *eq) 265{ 266 pprint_expr(i, dst, eq->LHS); 267 if (eq->sign == 0) 268 fprintf(dst, " == "); 269 else if (eq->sign > 0) 270 fprintf(dst, " >= "); 271 else 272 fprintf(dst, " <= "); 273 pprint_expr(i, dst, eq->RHS); 274} 275 276void pprint_assignment(struct cloogoptions *i, FILE *dst, 277 struct clast_assignment *a) 278{ 279 if (a->LHS) 280 fprintf(dst, "%s = ", a->LHS); 281 pprint_expr(i, dst, a->RHS); 282} 283 284 285/** 286 * pprint_osl_body function: 287 * this function pretty-prints the OpenScop body of a given statement. 288 * It returns 1 if it succeeds to find an OpenScop body to print for 289 * that statement, 0 otherwise. 290 * \param[in] options CLooG Options. 291 * \param[in] dst Output stream. 292 * \param[in] u Statement to print the OpenScop body. 293 * \return 1 on success to pretty-print an OpenScop body for u, 0 otherwise. 294 */ 295int pprint_osl_body(struct cloogoptions *options, FILE *dst, 296 struct clast_user_stmt *u) { 297#ifdef OSL_SUPPORT 298 int i; 299 char *expr, *tmp; 300 struct clast_stmt *t; 301 osl_scop_p scop = options->scop; 302 osl_statement_p stmt; 303 osl_body_p body; 304 305 if ((scop != NULL) && 306 (osl_statement_number(scop->statement) >= u->statement->number)) { 307 stmt = scop->statement; 308 309 /* Go to the convenient statement in the SCoP. */ 310 for (i = 1; i < u->statement->number; i++) 311 stmt = stmt->next; 312 313 /* Ensure it has a printable body. */ 314 if ((osl_generic_has_URI(stmt->body, OSL_URI_BODY)) && 315 ((body = stmt->body->data) != NULL) && 316 (body->expression != NULL) && 317 (body->iterators != NULL)) { 318 expr = osl_util_identifier_substitution(body->expression->string[0], 319 body->iterators->string); 320 tmp = expr; 321 /* Print the body expression, substituting the @...@ markers. */ 322 while (*expr) { 323 if (*expr == '@') { 324 int iterator; 325 expr += sscanf(expr, "@%d", &iterator) + 2; /* 2 for the @s */ 326 t = u->substitutions; 327 for (i = 0; i < iterator; i++) 328 t = t->next; 329 pprint_assignment(options, dst, (struct clast_assignment *)t); 330 } else { 331 fprintf(dst, "%c", *expr++); 332 } 333 } 334 fprintf(dst, "\n"); 335 free(tmp); 336 return 1; 337 } 338 } 339#endif 340 return 0; 341} 342 343void pprint_user_stmt(struct cloogoptions *options, FILE *dst, 344 struct clast_user_stmt *u) 345{ 346 struct clast_stmt *t; 347 348 if (pprint_osl_body(options, dst, u)) 349 return; 350 351 if (u->statement->name) 352 fprintf(dst, "%s", u->statement->name); 353 else 354 fprintf(dst, "S%d", u->statement->number); 355 fprintf(dst, "("); 356 for (t = u->substitutions; t; t = t->next) { 357 assert(CLAST_STMT_IS_A(t, stmt_ass)); 358 pprint_assignment(options, dst, (struct clast_assignment *)t); 359 if (t->next) 360 fprintf(dst, ","); 361 } 362 fprintf(dst, ")"); 363 if (options->language != CLOOG_LANGUAGE_FORTRAN) 364 fprintf(dst, ";"); 365 fprintf(dst, "\n"); 366} 367 368void pprint_guard(struct cloogoptions *options, FILE *dst, int indent, 369 struct clast_guard *g) 370{ 371 int k; 372 if (options->language == CLOOG_LANGUAGE_FORTRAN) 373 fprintf(dst,"IF "); 374 else 375 fprintf(dst,"if "); 376 if (g->n > 1) 377 fprintf(dst,"("); 378 for (k = 0; k < g->n; ++k) { 379 if (k > 0) { 380 if (options->language == CLOOG_LANGUAGE_FORTRAN) 381 fprintf(dst," .AND. "); 382 else 383 fprintf(dst," && "); 384 } 385 fprintf(dst,"("); 386 pprint_equation(options, dst, &g->eq[k]); 387 fprintf(dst,")"); 388 } 389 if (g->n > 1) 390 fprintf(dst,")"); 391 if (options->language == CLOOG_LANGUAGE_FORTRAN) 392 fprintf(dst," THEN\n"); 393 else 394 fprintf(dst," {\n"); 395 396 pprint_stmt_list(options, dst, indent + INDENT_STEP, g->then); 397 398 fprintf(dst, "%*s", indent, ""); 399 if (options->language == CLOOG_LANGUAGE_FORTRAN) 400 fprintf(dst,"END IF\n"); 401 else 402 fprintf(dst,"}\n"); 403} 404 405void pprint_for(struct cloogoptions *options, FILE *dst, int indent, 406 struct clast_for *f) 407{ 408 if (options->language == CLOOG_LANGUAGE_C) { 409 if ((f->parallel & CLAST_PARALLEL_OMP) && !(f->parallel & CLAST_PARALLEL_MPI)) { 410 if (f->LB) { 411 fprintf(dst, "lbp="); 412 pprint_expr(options, dst, f->LB); 413 fprintf(dst, ";\n"); 414 } 415 if (f->UB) { 416 fprintf(dst, "%*s", indent, ""); 417 fprintf(dst, "ubp="); 418 pprint_expr(options, dst, f->UB); 419 fprintf(dst, ";\n"); 420 } 421 fprintf(dst, "#pragma omp parallel for%s%s%s%s%s%s\n", 422 (f->private_vars)? " private(":"", 423 (f->private_vars)? f->private_vars: "", 424 (f->private_vars)? ")":"", 425 (f->reduction_vars)? " reduction(": "", 426 (f->reduction_vars)? f->reduction_vars: "", 427 (f->reduction_vars)? ")": ""); 428 fprintf(dst, "%*s", indent, ""); 429 } 430 if ((f->parallel & CLAST_PARALLEL_VEC) && !(f->parallel & CLAST_PARALLEL_OMP) 431 && !(f->parallel & CLAST_PARALLEL_MPI)) { 432 if (f->LB) { 433 fprintf(dst, "lbv="); 434 pprint_expr(options, dst, f->LB); 435 fprintf(dst, ";\n"); 436 } 437 if (f->UB) { 438 fprintf(dst, "%*s", indent, ""); 439 fprintf(dst, "ubv="); 440 pprint_expr(options, dst, f->UB); 441 fprintf(dst, ";\n"); 442 } 443 fprintf(dst, "%*s#pragma ivdep\n", indent, ""); 444 fprintf(dst, "%*s#pragma vector always\n", indent, ""); 445 fprintf(dst, "%*s", indent, ""); 446 } 447 if (f->parallel & CLAST_PARALLEL_MPI) { 448 if (f->LB) { 449 fprintf(dst, "_lb_dist="); 450 pprint_expr(options, dst, f->LB); 451 fprintf(dst, ";\n"); 452 } 453 if (f->UB) { 454 fprintf(dst, "%*s", indent, ""); 455 fprintf(dst, "_ub_dist="); 456 pprint_expr(options, dst, f->UB); 457 fprintf(dst, ";\n"); 458 } 459 fprintf(dst, "%*s", indent, ""); 460 fprintf(dst, "polyrt_loop_dist(_lb_dist, _ub_dist, nprocs, my_rank, &lbp, &ubp);\n"); 461 if (f->parallel & CLAST_PARALLEL_OMP) { 462 fprintf(dst, "#pragma omp parallel for%s%s%s%s%s%s\n", 463 (f->private_vars)? " private(":"", 464 (f->private_vars)? f->private_vars: "", 465 (f->private_vars)? ")":"", 466 (f->reduction_vars)? " reduction(": "", 467 (f->reduction_vars)? f->reduction_vars: "", 468 (f->reduction_vars)? ")": ""); 469 } 470 fprintf(dst, "%*s", indent, ""); 471 } 472 473 } 474 475 if (options->language == CLOOG_LANGUAGE_FORTRAN) 476 fprintf(dst, "DO "); 477 else 478 fprintf(dst, "for ("); 479 480 if (f->LB) { 481 fprintf(dst, "%s=", f->iterator); 482 if (f->parallel & (CLAST_PARALLEL_OMP | CLAST_PARALLEL_MPI)) { 483 fprintf(dst, "lbp"); 484 }else if (f->parallel & CLAST_PARALLEL_VEC){ 485 fprintf(dst, "lbv"); 486 }else{ 487 pprint_expr(options, dst, f->LB); 488 } 489 } else if (options->language == CLOOG_LANGUAGE_FORTRAN) 490 cloog_die("unbounded loops not allowed in FORTRAN.\n"); 491 492 if (options->language == CLOOG_LANGUAGE_FORTRAN) 493 fprintf(dst,", "); 494 else 495 fprintf(dst,";"); 496 497 if (f->UB) { 498 if (options->language != CLOOG_LANGUAGE_FORTRAN) 499 fprintf(dst,"%s<=", f->iterator); 500 501 if (f->parallel & (CLAST_PARALLEL_OMP | CLAST_PARALLEL_MPI)) { 502 fprintf(dst, "ubp"); 503 }else if (f->parallel & CLAST_PARALLEL_VEC){ 504 fprintf(dst, "ubv"); 505 }else{ 506 pprint_expr(options, dst, f->UB); 507 } 508 }else if (options->language == CLOOG_LANGUAGE_FORTRAN) 509 cloog_die("unbounded loops not allowed in FORTRAN.\n"); 510 511 if (options->language == CLOOG_LANGUAGE_FORTRAN) { 512 if (cloog_int_gt_si(f->stride, 1)) 513 cloog_int_print(dst, f->stride); 514 fprintf(dst,"\n"); 515 } 516 else { 517 if (cloog_int_gt_si(f->stride, 1)) { 518 fprintf(dst,";%s+=", f->iterator); 519 cloog_int_print(dst, f->stride); 520 fprintf(dst, ") {\n"); 521 } else 522 fprintf(dst, ";%s++) {\n", f->iterator); 523 } 524 525 pprint_stmt_list(options, dst, indent + INDENT_STEP, f->body); 526 527 fprintf(dst, "%*s", indent, ""); 528 if (options->language == CLOOG_LANGUAGE_FORTRAN) 529 fprintf(dst,"END DO\n") ; 530 else 531 fprintf(dst,"}\n") ; 532} 533 534void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent, 535 struct clast_stmt *s) 536{ 537 for ( ; s; s = s->next) { 538 if (CLAST_STMT_IS_A(s, stmt_root)) 539 continue; 540 fprintf(dst, "%*s", indent, ""); 541 if (CLAST_STMT_IS_A(s, stmt_ass)) { 542 pprint_assignment(options, dst, (struct clast_assignment *) s); 543 if (options->language != CLOOG_LANGUAGE_FORTRAN) 544 fprintf(dst, ";"); 545 fprintf(dst, "\n"); 546 } else if (CLAST_STMT_IS_A(s, stmt_user)) { 547 pprint_user_stmt(options, dst, (struct clast_user_stmt *) s); 548 } else if (CLAST_STMT_IS_A(s, stmt_for)) { 549 pprint_for(options, dst, indent, (struct clast_for *) s); 550 } else if (CLAST_STMT_IS_A(s, stmt_guard)) { 551 pprint_guard(options, dst, indent, (struct clast_guard *) s); 552 } else if (CLAST_STMT_IS_A(s, stmt_block)) { 553 fprintf(dst, "{\n"); 554 pprint_stmt_list(options, dst, indent + INDENT_STEP, 555 ((struct clast_block *)s)->body); 556 fprintf(dst, "%*s", indent, ""); 557 fprintf(dst, "}\n"); 558 } else { 559 assert(0); 560 } 561 } 562} 563 564 565/****************************************************************************** 566 * Pretty Printing (dirty) functions * 567 ******************************************************************************/ 568 569void clast_pprint(FILE *foo, struct clast_stmt *root, 570 int indent, CloogOptions *options) 571{ 572 pprint_stmt_list(options, foo, indent, root); 573} 574