2 /**-------------------------------------------------------------------**
4 **-------------------------------------------------------------------**
6 **-------------------------------------------------------------------**
7 ** First version: october 26th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2001-2005 Cedric Bastoul *
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. *
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. *
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 *
32 * CLooG, the Chunky Loop Generator *
33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
35 ******************************************************************************/
36 /* CAUTION: the english used for comments is probably the worst you ever read,
37 * please feel free to correct and improve it !
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.
51 # include "../include/cloog/cloog.h"
56 #include <osl/extensions/extbody.h>
57 #include <osl/statement.h>
62 static void pprint_name(FILE *dst
, struct clast_name
*n
);
63 static void pprint_term(struct cloogoptions
*i
, FILE *dst
, struct clast_term
*t
);
64 static void pprint_sum(struct cloogoptions
*opt
,
65 FILE *dst
, struct clast_reduction
*r
);
66 static void pprint_binary(struct cloogoptions
*i
,
67 FILE *dst
, struct clast_binary
*b
);
68 static void pprint_minmax_f(struct cloogoptions
*info
,
69 FILE *dst
, struct clast_reduction
*r
);
70 static void pprint_minmax_c(struct cloogoptions
*info
,
71 FILE *dst
, struct clast_reduction
*r
);
72 static void pprint_reduction(struct cloogoptions
*i
,
73 FILE *dst
, struct clast_reduction
*r
);
74 static void pprint_expr(struct cloogoptions
*i
, FILE *dst
, struct clast_expr
*e
);
75 static void pprint_equation(struct cloogoptions
*i
,
76 FILE *dst
, struct clast_equation
*eq
);
77 static void pprint_assignment(struct cloogoptions
*i
, FILE *dst
,
78 struct clast_assignment
*a
);
79 static void pprint_user_stmt(struct cloogoptions
*options
, FILE *dst
,
80 struct clast_user_stmt
*u
);
81 static void pprint_guard(struct cloogoptions
*options
, FILE *dst
, int indent
,
82 struct clast_guard
*g
);
83 static void pprint_for(struct cloogoptions
*options
, FILE *dst
, int indent
,
85 static void pprint_stmt_list(struct cloogoptions
*options
, FILE *dst
, int indent
,
86 struct clast_stmt
*s
);
89 void pprint_name(FILE *dst
, struct clast_name
*n
)
91 fprintf(dst
, "%s", n
->name
);
95 * This function returns a string containing the printing of a value (possibly
96 * an iterator or a parameter with its coefficient or a constant).
97 * - val is the coefficient or constant value,
98 * - name is a string containing the name of the iterator or of the parameter,
100 void pprint_term(struct cloogoptions
*i
, FILE *dst
, struct clast_term
*t
)
103 int group
= t
->var
->type
== clast_expr_red
&&
104 ((struct clast_reduction
*) t
->var
)->n
> 1;
105 if (cloog_int_is_one(t
->val
))
107 else if (cloog_int_is_neg_one(t
->val
))
110 cloog_int_print(dst
, t
->val
);
115 pprint_expr(i
, dst
, t
->var
);
119 cloog_int_print(dst
, t
->val
);
122 void pprint_sum(struct cloogoptions
*opt
, FILE *dst
, struct clast_reduction
*r
)
125 struct clast_term
*t
;
128 assert(r
->elts
[0]->type
== clast_expr_term
);
129 t
= (struct clast_term
*) r
->elts
[0];
130 pprint_term(opt
, dst
, t
);
132 for (i
= 1; i
< r
->n
; ++i
) {
133 assert(r
->elts
[i
]->type
== clast_expr_term
);
134 t
= (struct clast_term
*) r
->elts
[i
];
135 if (cloog_int_is_pos(t
->val
))
137 pprint_term(opt
, dst
, t
);
141 void pprint_binary(struct cloogoptions
*i
, FILE *dst
, struct clast_binary
*b
)
143 const char *s1
= NULL
, *s2
= NULL
, *s3
= NULL
;
144 int group
= b
->LHS
->type
== clast_expr_red
&&
145 ((struct clast_reduction
*) b
->LHS
)->n
> 1;
146 if (i
->language
== CLOOG_LANGUAGE_FORTRAN
) {
149 s1
= "FLOOR(REAL(", s2
= ")/REAL(", s3
= "))";
152 s1
= "CEILING(REAL(", s2
= ")/REAL(", s3
= "))";
156 s1
= "(", s2
= ")/", s3
= "";
158 s1
= "", s2
= "/", s3
= "";
161 s1
= "MOD(", s2
= ", ", s3
= ")";
167 s1
= "floord(", s2
= ",", s3
= ")";
170 s1
= "ceild(", s2
= ",", s3
= ")";
174 s1
= "(", s2
= ")/", s3
= "";
176 s1
= "", s2
= "/", s3
= "";
180 s1
= "(", s2
= ")%", s3
= "";
182 s1
= "", s2
= "%", s3
= "";
186 fprintf(dst
, "%s", s1
);
187 pprint_expr(i
, dst
, b
->LHS
);
188 fprintf(dst
, "%s", s2
);
189 cloog_int_print(dst
, b
->RHS
);
190 fprintf(dst
, "%s", s3
);
193 void pprint_minmax_f(struct cloogoptions
*info
, FILE *dst
, struct clast_reduction
*r
)
198 fprintf(dst
, r
->type
== clast_red_max
? "MAX(" : "MIN(");
199 pprint_expr(info
, dst
, r
->elts
[0]);
200 for (i
= 1; i
< r
->n
; ++i
) {
202 pprint_expr(info
, dst
, r
->elts
[i
]);
207 void pprint_minmax_c(struct cloogoptions
*info
, FILE *dst
, struct clast_reduction
*r
)
210 for (i
= 1; i
< r
->n
; ++i
)
211 fprintf(dst
, r
->type
== clast_red_max
? "max(" : "min(");
213 pprint_expr(info
, dst
, r
->elts
[0]);
214 for (i
= 1; i
< r
->n
; ++i
) {
216 pprint_expr(info
, dst
, r
->elts
[i
]);
221 void pprint_reduction(struct cloogoptions
*i
, FILE *dst
, struct clast_reduction
*r
)
225 pprint_sum(i
, dst
, r
);
230 pprint_expr(i
, dst
, r
->elts
[0]);
233 if (i
->language
== CLOOG_LANGUAGE_FORTRAN
)
234 pprint_minmax_f(i
, dst
, r
);
236 pprint_minmax_c(i
, dst
, r
);
243 void pprint_expr(struct cloogoptions
*i
, FILE *dst
, struct clast_expr
*e
)
248 case clast_expr_name
:
249 pprint_name(dst
, (struct clast_name
*) e
);
251 case clast_expr_term
:
252 pprint_term(i
, dst
, (struct clast_term
*) e
);
255 pprint_reduction(i
, dst
, (struct clast_reduction
*) e
);
258 pprint_binary(i
, dst
, (struct clast_binary
*) e
);
265 void pprint_equation(struct cloogoptions
*i
, FILE *dst
, struct clast_equation
*eq
)
267 pprint_expr(i
, dst
, eq
->LHS
);
269 fprintf(dst
, " == ");
270 else if (eq
->sign
> 0)
271 fprintf(dst
, " >= ");
273 fprintf(dst
, " <= ");
274 pprint_expr(i
, dst
, eq
->RHS
);
277 void pprint_assignment(struct cloogoptions
*i
, FILE *dst
,
278 struct clast_assignment
*a
)
281 fprintf(dst
, "%s = ", a
->LHS
);
282 pprint_expr(i
, dst
, a
->RHS
);
287 * pprint_osl_body function:
288 * this function pretty-prints the OpenScop body of a given statement.
289 * It returns 1 if it succeeds to find an OpenScop body to print for
290 * that statement, 0 otherwise.
291 * \param[in] options CLooG Options.
292 * \param[in] dst Output stream.
293 * \param[in] u Statement to print the OpenScop body.
294 * \return 1 on success to pretty-print an OpenScop body for u, 0 otherwise.
296 int pprint_osl_body(struct cloogoptions
*options
, FILE *dst
,
297 struct clast_user_stmt
*u
) {
301 struct clast_stmt
*t
;
302 osl_scop_p scop
= options
->scop
;
303 osl_statement_p stmt
;
306 if ((scop
!= NULL
) &&
307 (osl_statement_number(scop
->statement
) >= u
->statement
->number
)) {
308 stmt
= scop
->statement
;
310 /* Go to the convenient statement in the SCoP. */
311 for (i
= 1; i
< u
->statement
->number
; i
++)
314 /* Ensure it has a printable body. */
315 body
= osl_statement_get_body(stmt
);
316 if ((body
!= NULL
) &&
317 (body
->expression
!= NULL
) &&
318 (body
->iterators
!= NULL
)) {
319 expr
= osl_util_identifier_substitution(body
->expression
->string
[0],
320 body
->iterators
->string
);
322 /* Print the body expression, substituting the @...@ markers. */
326 expr
+= sscanf(expr
, "@%d", &iterator
) + 2; /* 2 for the @s */
327 t
= u
->substitutions
;
328 for (i
= 0; i
< iterator
; i
++)
330 pprint_assignment(options
, dst
, (struct clast_assignment
*)t
);
332 fprintf(dst
, "%c", *expr
++);
344 /* pprint_parentheses_are_safer function:
345 * this function returns 1 if it decides that it would be safer to put
346 * parentheses around the clast_assignment when it is used as a macro
347 * parameter, 0 otherwise.
348 * \param[in] s Pointer to the clast_assignment to check.
349 * \return 1 if we should print parentheses around s, 0 otherwise.
351 static int pprint_parentheses_are_safer(struct clast_assignment
* s
) {
352 /* Expressions of the form X = Y should not be used in macros, so we
353 * consider readability first for them and avoid parentheses.
354 * Also, expressions having only one term can live without parentheses.
357 (s
->RHS
->type
== clast_expr_term
) ||
358 ((s
->RHS
->type
== clast_expr_red
) &&
359 (((struct clast_reduction
*)(s
->RHS
))->n
== 1) &&
360 (((struct clast_reduction
*)(s
->RHS
))->elts
[0]->type
==
367 void pprint_user_stmt(struct cloogoptions
*options
, FILE *dst
,
368 struct clast_user_stmt
*u
)
370 int parenthesis_to_close
= 0;
371 struct clast_stmt
*t
;
373 if (pprint_osl_body(options
, dst
, u
))
376 if (u
->statement
->name
)
377 fprintf(dst
, "%s", u
->statement
->name
);
379 fprintf(dst
, "S%d", u
->statement
->number
);
381 for (t
= u
->substitutions
; t
; t
= t
->next
) {
382 assert(CLAST_STMT_IS_A(t
, stmt_ass
));
383 if (pprint_parentheses_are_safer((struct clast_assignment
*)t
)) {
385 parenthesis_to_close
= 1;
387 pprint_assignment(options
, dst
, (struct clast_assignment
*)t
);
389 if (parenthesis_to_close
) {
391 parenthesis_to_close
= 0;
396 if (parenthesis_to_close
)
399 if (options
->language
!= CLOOG_LANGUAGE_FORTRAN
)
404 void pprint_guard(struct cloogoptions
*options
, FILE *dst
, int indent
,
405 struct clast_guard
*g
)
408 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
414 for (k
= 0; k
< g
->n
; ++k
) {
416 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
417 fprintf(dst
," .AND. ");
422 pprint_equation(options
, dst
, &g
->eq
[k
]);
427 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
428 fprintf(dst
," THEN\n");
432 pprint_stmt_list(options
, dst
, indent
+ INDENT_STEP
, g
->then
);
434 fprintf(dst
, "%*s", indent
, "");
435 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
436 fprintf(dst
,"END IF\n");
441 void pprint_for(struct cloogoptions
*options
, FILE *dst
, int indent
,
444 if (options
->language
== CLOOG_LANGUAGE_C
) {
445 if (f
->time_var_name
) {
446 fprintf(dst
, "IF_TIME(%s_start = cloog_util_rtclock());\n",
447 (f
->time_var_name
) ? f
->time_var_name
: "");
449 if ((f
->parallel
& CLAST_PARALLEL_OMP
) && !(f
->parallel
& CLAST_PARALLEL_MPI
)) {
451 fprintf(dst
, "lbp=");
452 pprint_expr(options
, dst
, f
->LB
);
456 fprintf(dst
, "%*s", indent
, "");
457 fprintf(dst
, "ubp=");
458 pprint_expr(options
, dst
, f
->UB
);
462 fprintf(dst
, "_Pragma(\"omp %s for%s%s%s%s%s%s\")\n",
463 (f
->parallel
&CLAST_PARALLEL_FORMAT_BARE
)? "":"parallel",
464 (f
->private_vars
)? " private(":"",
465 (f
->private_vars
)? f
->private_vars
: "",
466 (f
->private_vars
)? ")":"",
467 (f
->reduction_vars
)? " reduction(": "",
468 (f
->reduction_vars
)? f
->reduction_vars
: "",
469 (f
->reduction_vars
)? ")": "");
471 fprintf(dst
, "#pragma omp %s for%s%s%s%s%s%s\n",
472 (f
->parallel
&CLAST_PARALLEL_FORMAT_BARE
)? "":"parallel",
473 (f
->private_vars
)? " private(":"",
474 (f
->private_vars
)? f
->private_vars
: "",
475 (f
->private_vars
)? ")":"",
476 (f
->reduction_vars
)? " reduction(": "",
477 (f
->reduction_vars
)? f
->reduction_vars
: "",
478 (f
->reduction_vars
)? ")": "");
480 fprintf(dst
, "%*s", indent
, "");
482 if ((f
->parallel
& CLAST_PARALLEL_VEC
) && !(f
->parallel
& CLAST_PARALLEL_OMP
)
483 && !(f
->parallel
& CLAST_PARALLEL_MPI
)) {
485 fprintf(dst
, "lbv=");
486 pprint_expr(options
, dst
, f
->LB
);
490 fprintf(dst
, "%*s", indent
, "");
491 fprintf(dst
, "ubv=");
492 pprint_expr(options
, dst
, f
->UB
);
495 if(options
->use_c99
) {
496 fprintf(dst
, "%*s_Pragma(\"ivdep\")\n", indent
, "");
497 fprintf(dst
, "%*s_Pragma(\"vector always\")\n", indent
, "");
499 fprintf(dst
, "%*s#pragma ivdep \n", indent
, "");
500 fprintf(dst
, "%*s#pragma vector always \n", indent
, "");
502 fprintf(dst
, "%*s", indent
, "");
504 if (f
->parallel
& CLAST_PARALLEL_MPI
) {
506 fprintf(dst
, "_lb_dist=");
507 pprint_expr(options
, dst
, f
->LB
);
511 fprintf(dst
, "%*s", indent
, "");
512 fprintf(dst
, "_ub_dist=");
513 pprint_expr(options
, dst
, f
->UB
);
516 fprintf(dst
, "%*s", indent
, "");
517 fprintf(dst
, "polyrt_loop_dist(_lb_dist, _ub_dist, nprocs, my_rank, &lbp, &ubp);\n");
518 if (f
->parallel
& CLAST_PARALLEL_OMP
) {
520 fprintf(dst
, "_Pragma(\"omp %s for%s%s%s%s%s%s\")\n",
521 (f
->parallel
&CLAST_PARALLEL_FORMAT_BARE
)? "":"parallel",
522 (f
->private_vars
)? " private(":"",
523 (f
->private_vars
)? f
->private_vars
: "",
524 (f
->private_vars
)? ")":"",
525 (f
->reduction_vars
)? " reduction(": "",
526 (f
->reduction_vars
)? f
->reduction_vars
: "",
527 (f
->reduction_vars
)? ")": "");
529 fprintf(dst
, "#pragma omp %s for%s%s%s%s%s%s\n",
530 (f
->parallel
&CLAST_PARALLEL_FORMAT_BARE
)? "":"parallel",
531 (f
->private_vars
)? " private(":"",
532 (f
->private_vars
)? f
->private_vars
: "",
533 (f
->private_vars
)? ")":"",
534 (f
->reduction_vars
)? " reduction(": "",
535 (f
->reduction_vars
)? f
->reduction_vars
: "",
536 (f
->reduction_vars
)? ")": "");
538 fprintf(dst
, "%*s", indent
, "");
543 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
546 fprintf(dst
, "for (");
549 fprintf(dst
, "%s=", f
->iterator
);
550 if (f
->parallel
& (CLAST_PARALLEL_OMP
| CLAST_PARALLEL_MPI
)) {
552 }else if (f
->parallel
& CLAST_PARALLEL_VEC
){
555 pprint_expr(options
, dst
, f
->LB
);
557 } else if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
558 cloog_die("unbounded loops not allowed in FORTRAN.\n");
560 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
566 if (options
->language
!= CLOOG_LANGUAGE_FORTRAN
)
567 fprintf(dst
,"%s<=", f
->iterator
);
569 if (f
->parallel
& (CLAST_PARALLEL_OMP
| CLAST_PARALLEL_MPI
)) {
571 }else if (f
->parallel
& CLAST_PARALLEL_VEC
){
574 pprint_expr(options
, dst
, f
->UB
);
576 }else if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
577 cloog_die("unbounded loops not allowed in FORTRAN.\n");
579 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
) {
580 if (cloog_int_gt_si(f
->stride
, 1))
581 cloog_int_print(dst
, f
->stride
);
585 if (cloog_int_gt_si(f
->stride
, 1)) {
586 fprintf(dst
,";%s+=", f
->iterator
);
587 cloog_int_print(dst
, f
->stride
);
588 fprintf(dst
, ") {\n");
590 fprintf(dst
, ";%s++) {\n", f
->iterator
);
593 pprint_stmt_list(options
, dst
, indent
+ INDENT_STEP
, f
->body
);
595 fprintf(dst
, "%*s", indent
, "");
596 if (options
->language
== CLOOG_LANGUAGE_FORTRAN
)
597 fprintf(dst
,"END DO\n") ;
601 if (options
->language
== CLOOG_LANGUAGE_C
) {
602 if (f
->time_var_name
) {
603 fprintf(dst
, "IF_TIME(%s += cloog_util_rtclock() - %s_start);\n",
604 (f
->time_var_name
) ? f
->time_var_name
: "",
605 (f
->time_var_name
) ? f
->time_var_name
: "");
610 void pprint_stmt_list(struct cloogoptions
*options
, FILE *dst
, int indent
,
611 struct clast_stmt
*s
)
613 for ( ; s
; s
= s
->next
) {
614 if (CLAST_STMT_IS_A(s
, stmt_root
))
616 fprintf(dst
, "%*s", indent
, "");
617 if (CLAST_STMT_IS_A(s
, stmt_ass
)) {
618 pprint_assignment(options
, dst
, (struct clast_assignment
*) s
);
619 if (options
->language
!= CLOOG_LANGUAGE_FORTRAN
)
622 } else if (CLAST_STMT_IS_A(s
, stmt_user
)) {
623 pprint_user_stmt(options
, dst
, (struct clast_user_stmt
*) s
);
624 } else if (CLAST_STMT_IS_A(s
, stmt_for
)) {
625 pprint_for(options
, dst
, indent
, (struct clast_for
*) s
);
626 } else if (CLAST_STMT_IS_A(s
, stmt_guard
)) {
627 pprint_guard(options
, dst
, indent
, (struct clast_guard
*) s
);
628 } else if (CLAST_STMT_IS_A(s
, stmt_block
)) {
630 pprint_stmt_list(options
, dst
, indent
+ INDENT_STEP
,
631 ((struct clast_block
*)s
)->body
);
632 fprintf(dst
, "%*s", indent
, "");
641 /******************************************************************************
642 * Pretty Printing (dirty) functions *
643 ******************************************************************************/
645 void clast_pprint(FILE *foo
, struct clast_stmt
*root
,
646 int indent
, CloogOptions
*options
)
648 pprint_stmt_list(options
, foo
, indent
, root
);
652 void clast_pprint_expr(struct cloogoptions
*i
, FILE *dst
, struct clast_expr
*e
)
654 pprint_expr(i
, dst
, e
);