1 /*
2  * Copyright 2010-2011 INRIA Saclay
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8  * 91893 Orsay, France
9  */
10 
11 #include <assert.h>
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include <isl/set.h>
17 #include <isl/map.h>
18 #include <isl/constraint.h>
19 
20 #include "schedule.h"
21 
22 /* Add parameters with identifiers "ids" to "set".
23  */
add_params(__isl_take isl_set * set,__isl_keep isl_id_list * ids)24 static __isl_give isl_set *add_params(__isl_take isl_set *set,
25 	__isl_keep isl_id_list *ids)
26 {
27 	int i, n;
28 	unsigned nparam;
29 
30 	n = isl_id_list_n_id(ids);
31 
32 	nparam = isl_set_dim(set, isl_dim_param);
33 	set = isl_set_add_dims(set, isl_dim_param, n);
34 
35 	for (i = 0; i < n; ++i) {
36 		isl_id *id;
37 
38 		id = isl_id_list_get_id(ids, i);
39 		set = isl_set_set_dim_id(set, isl_dim_param, nparam + i, id);
40 	}
41 
42 	return set;
43 }
44 
45 /* Equate the dimensions of "set" starting at "first" to
46  * freshly created parameters with identifiers "ids".
47  * The number of equated dimensions is equal to the number of elements in "ids".
48  */
parametrize(__isl_take isl_set * set,int first,__isl_keep isl_id_list * ids)49 static __isl_give isl_set *parametrize(__isl_take isl_set *set,
50 	int first, __isl_keep isl_id_list *ids)
51 {
52 	int i, n;
53 	unsigned nparam;
54 
55 	nparam = isl_set_dim(set, isl_dim_param);
56 
57 	set = add_params(set, ids);
58 
59 	n = isl_id_list_n_id(ids);
60 	for (i = 0; i < n; ++i)
61 		set = isl_set_equate(set, isl_dim_param, nparam + i,
62 					isl_dim_set, first + i);
63 
64 	return set;
65 }
66 
67 /* Given a parameter space "space", create a set of dimension "len"
68  * of which the dimensions starting at "first" are equated to
69  * freshly created parameters with identifiers "ids".
70  */
parametrization(__isl_take isl_space * space,int len,int first,__isl_keep isl_id_list * ids)71 __isl_give isl_set *parametrization(__isl_take isl_space *space,
72 	int len, int first, __isl_keep isl_id_list *ids)
73 {
74 	isl_set *set;
75 
76 	space = isl_space_set_from_params(space);
77 	space = isl_space_add_dims(space, isl_dim_set, len);
78 	set = isl_set_universe(space);
79 
80 	return parametrize(set, first, ids);
81 }
82 
83 /* Load and return a schedule from a file called "filename".
84  */
load_schedule(isl_ctx * ctx,const char * filename)85 static __isl_give isl_schedule *load_schedule(isl_ctx *ctx,
86 	const char *filename)
87 {
88 	FILE *file;
89 	isl_schedule *schedule;
90 
91 	file = fopen(filename, "r");
92 	if (!file) {
93 		fprintf(stderr, "Unable to open '%s' for reading\n", filename);
94 		return NULL;
95 	}
96 	schedule = isl_schedule_read_from_file(ctx, file);
97 	fclose(file);
98 
99 	return schedule;
100 }
101 
102 /* Save the schedule "schedule" to a file called "filename".
103  * The schedule is printed in block style.
104  */
save_schedule(__isl_keep isl_schedule * schedule,const char * filename)105 static void save_schedule(__isl_keep isl_schedule *schedule,
106 	const char *filename)
107 {
108 	FILE *file;
109 	isl_ctx *ctx;
110 	isl_printer *p;
111 
112 	if (!schedule)
113 		return;
114 
115 	file = fopen(filename, "w");
116 	if (!file) {
117 		fprintf(stderr, "Unable to open '%s' for writing\n", filename);
118 		return;
119 	}
120 	ctx = isl_schedule_get_ctx(schedule);
121 	p = isl_printer_to_file(ctx, file);
122 	p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
123 	p = isl_printer_print_schedule(p, schedule);
124 	isl_printer_free(p);
125 	fclose(file);
126 }
127 
128 /* Obtain a schedule, either by reading it form a file
129  * or by computing it using "compute".
130  * Also take care of saving the computed schedule and/or
131  * dumping the obtained schedule if requested by the user.
132  */
ppcg_get_schedule(isl_ctx * ctx,struct ppcg_options * options,__isl_give isl_schedule * (* compute)(void * user),void * user)133 __isl_give isl_schedule *ppcg_get_schedule(isl_ctx *ctx,
134 	struct ppcg_options *options,
135 	__isl_give isl_schedule *(*compute)(void *user), void *user)
136 {
137 	isl_schedule *schedule;
138 
139 	if (options->load_schedule_file) {
140 		schedule = load_schedule(ctx, options->load_schedule_file);
141 	} else {
142 		schedule = compute(user);
143 		if (options->save_schedule_file)
144 			save_schedule(schedule, options->save_schedule_file);
145 	}
146 	if (options->debug->dump_schedule)
147 		isl_schedule_dump(schedule);
148 
149 	return schedule;
150 }
151 
152 /* Mark all dimensions in the band node "node" to be of "type".
153  */
ppcg_set_schedule_node_type(__isl_take isl_schedule_node * node,enum isl_ast_loop_type type)154 __isl_give isl_schedule_node *ppcg_set_schedule_node_type(
155 	__isl_take isl_schedule_node *node, enum isl_ast_loop_type type)
156 {
157 	int i, n;
158 
159 	n = isl_schedule_node_band_n_member(node);
160 	for (i = 0; i < n; ++i)
161 		node = isl_schedule_node_band_member_set_ast_loop_type(node, i,
162 							type);
163 
164 	return node;
165 }
166