PIPS
kernels.c
Go to the documentation of this file.
1 /*
2  Copyright 1989-2016 MINES ParisTech
3 
4  This file is part of PIPS.
5 
6  PIPS is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  any later version.
10 
11  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.
14 
15  See the GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 /**
23  * @file kernels.c
24  * kernels manipulation
25  * @author Serge Guelton <serge.guelton@enst-bretagne.fr>
26  * @date 2010-01-03
27  */
28 #ifdef HAVE_CONFIG_H
29  #include "pips_config.h"
30 #endif
31 #include <ctype.h>
32 
33 
34 #include "genC.h"
35 #include "linear.h"
36 #include "ri.h"
37 #include "effects.h"
38 #include "ri-util.h"
39 #include "effects-util.h"
40 #include "text.h"
41 #include "pipsdbm.h"
42 #include "resources.h"
43 #include "properties.h"
44 #include "misc.h"
45 #include "control.h"
46 #include "callgraph.h"
47 #include "effects-generic.h"
48 #include "effects-simple.h"
49 #include "effects-convex.h"
50 #include "text-util.h"
51 #include "transformations.h"
52 #include "transformer.h"
53 #include "semantics.h"
54 #include "parser_private.h"
55 #include "accel-util.h"
56 
57 
58 /* Generate a communication around a statement instead of plain memory
59  access if it is a call to a function named module_name
60 
61  @param[in,out] s is the statment to isolate with some communication arounds
62 
63  @param[in] module_name is the name of the function to isolate
64 */
65 static void
67 {
68  if(statement_call_p(s))
69  {
70  call c = statement_call(s);
71  /* Generate communication operations around the call to a function
72  named "module_name". */
74  {
75  const char* prefix = get_string_property ("KERNEL_LOAD_STORE_VAR_PREFIX");
76  const char* suffix = get_string_property ("KERNEL_LOAD_STORE_VAR_SUFFIX");
77  pips_debug (5, "kernel_load_store used prefix : %s\n", prefix);
78  pips_debug (5, "kernel_load_store used suffix : %s\n", suffix);
79  do_isolate_statement(s, prefix, suffix);
80  }
81  }
82 }
83 
84 /* run kernel load store using either region or effect engine
85 
86  @param[in] module_name is the name of the function we want to isolate
87  with communications and memory allocations
88 
89  @param[in] enginerc is the name of the resources to use to analyse
90  which data need to be allocated and transfers. It can be DBR_REGIONS
91  (more precise) or DBR_EFFECTS
92  */
93 static bool kernel_load_store_engine(const char* module_name,
94  const string enginerc) {
95  /* generate a load stores on each caller */
96 
97  debug_on("KERNEL_LOAD_STORE_DEBUG_LEVEL");
98 
99  callees callers = (callees)db_get_memory_resource(DBR_CALLERS,module_name,true);
101  /* prelude */
108  /*do the job */
111  /* validate */
115 
116  /*postlude*/
123  }
124 
125  /*flag the module as kernel if not done */
126  callees kernels = (callees)db_get_memory_resource(DBR_KERNELS,"",true);
127  bool found = false;
128  FOREACH(STRING,kernel_name,callees_callees(kernels))
129  if( (found=(same_string_p(kernel_name,module_name))) ) break;
130  if(!found)
132  db_put_or_update_memory_resource(DBR_KERNELS,"",kernels,true);
133 
134  debug_off();
135 
136  return true;
137 }
138 
139 
140 /** Generate malloc/copy-in/copy-out on the call sites of this module.
141  * based on convex array regions
142  */
143 bool kernel_load_store(const char* module_name) {
144  return kernel_load_store_engine(module_name, DBR_REGIONS);
145 }
146 
147 
148 
149 /**
150  * create a statement eligible for outlining into a kernel
151  * #1 find the loop flagged with loop_label
152  * #2 make sure the loop is // with local index
153  * #3 perform strip mining on this loop to make the kernel appear
154  * #4 perform two outlining to separate kernel from host
155  *
156  * @param s statement where the kernel can be found
157  * @param loop_label label of the loop to be turned into a kernel
158  *
159  * @return true as long as the kernel is not found
160  */
161 static
163 {
166  {
168  pips_user_error("you choosed a label of a non-doloop statement\n");
169 
170 
171 
173 
174  /* gather and check parameters */
175  int nb_nodes = get_int_property("KERNELIZE_NBNODES");
176  while(!nb_nodes)
177  {
178  string ur = user_request("number of nodes for your kernel?\n");
179  nb_nodes=atoi(ur);
180  }
181 
182  /* verify the loop is parallel */
184  pips_user_error("you tried to kernelize a sequential loop\n");
186  pips_user_error("you tried to kernelize a loop whose index is not private\n");
187 
188  if(nb_nodes >1 )
189  {
190  /* we can strip mine the loop */
192  /* unfortunately, the strip mining does not exactly does what we
193  want, fix it here
194 
195  it is legal because we know the loop index is private,
196  otherwise the end value of the loop index may be used
197  incorrectly...
198  */
199  {
201  entity outer_index = loop_index(statement_loop(s));
202  entity inner_index = loop_index(statement_loop(s2));
203  replace_entity(s2,inner_index,outer_index);
204  loop_index(statement_loop(s2))=outer_index;
205  replace_entity(loop_range(statement_loop(s2)),outer_index,inner_index);
206  if(!ENDP(loop_locals(statement_loop(s2)))) replace_entity(loop_locals(statement_loop(s2)),outer_index,inner_index);
207  loop_index(statement_loop(s))=inner_index;
208  replace_entity(loop_range(statement_loop(s)),outer_index,inner_index);
212  l = statement_loop(s);
213  }
214  }
215 
216  const char* kernel_name=get_string_property_or_ask("KERNELIZE_KERNEL_NAME","name of the kernel ?");
217  const char* host_call_name=get_string_property_or_ask("KERNELIZE_HOST_CALL_NAME","name of the fucntion to call the kernel ?");
218 
219  /* validate changes */
220  callees kernels=(callees)db_get_memory_resource(DBR_KERNELS,"",true);
221  callees_callees(kernels)= CONS(STRING,strdup(host_call_name),callees_callees(kernels));
222  DB_PUT_MEMORY_RESOURCE(DBR_KERNELS,"",kernels);
223 
231 
232  /* recompute effects */
233  proper_effects((string)module_local_name(cme));
234  cumulated_effects((string)module_local_name(cme));
238 
239  /* outline the work and kernel parts*/
240  outliner(kernel_name,make_statement_list(loop_body(l)));
241  (void)outliner(host_call_name,make_statement_list(s));
243 
244  /* job done */
245  gen_recurse_stop(NULL);
246 
247  }
248  return true;
249 }
250 
251 
252 /**
253  * turn a loop flagged with LOOP_LABEL into a kernel (GPU, terapix ...)
254  *
255  * @param module_name name of the module
256  *
257  * @return true
258  */
259 bool kernelize(const string module_name)
260 {
261  /* prelude */
264 
265  /* retreive loop label */
266  const char* loop_label_name = get_string_property_or_ask("LOOP_LABEL","label of the loop to turn into a kernel ?\n");
267  entity loop_label_entity = find_label_entity(module_name,loop_label_name);
268  if( entity_undefined_p(loop_label_entity) )
269  pips_user_error("label '%s' not found in module '%s' \n",loop_label_name,module_name);
270 
271 
272  /* run kernelize */
275 
276  /* validate */
280 
281  /*postlude*/
284  return true;
285 }
286 
287 bool flag_kernel(const string module_name)
288 {
289  if (!db_resource_p(DBR_KERNELS, ""))
290  pips_internal_error("kernels not initialized for %s", module_name);
291  callees kernels=(callees)db_get_memory_resource(DBR_KERNELS,"",true);
293  DB_PUT_MEMORY_RESOURCE(DBR_KERNELS,"",kernels);
294  return true;
295 }
296 
297 bool bootstrap_kernels(const string module_name)
298 {
299  if (db_resource_p(DBR_KERNELS, ""))
300  pips_internal_error("kernels already initialized for %s", module_name);
301  callees kernels=make_callees(NIL);
302  DB_PUT_MEMORY_RESOURCE(DBR_KERNELS,"",kernels);
303  return true;
304 }
305 
306 
int get_int_property(const string)
callees make_callees(list a)
Definition: ri.c:227
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
statement outliner(const char *, list)
outline the statements in statements_to_outline into a module named outline_module_name the outlined ...
Definition: outlining.c:1327
void do_isolate_statement(statement, const char *, const char *)
perform statement isolation on statement s that is make sure that all access to variables in s are ma...
static const char * caller_name
Definition: alias_check.c:122
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
void reset_cumulated_rw_effects(void)
bool cumulated_effects(const string)
bool proper_effects(const string)
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * get_string_property(const char *)
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define STRING(x)
Definition: genC.h:87
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
void db_put_or_update_memory_resource(const char *rname, const char *oname, void *p, bool update_is_ok)
Put a resource into the current workspace database.
Definition: database.c:854
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
bool statement_call_p(statement)
Definition: statement.c:364
bool statement_loop_p(statement)
Definition: statement.c:349
bool kernelize(const string module_name)
turn a loop flagged with LOOP_LABEL into a kernel (GPU, terapix ...)
Definition: kernels.c:259
bool flag_kernel(const string module_name)
Definition: kernels.c:287
static void kernel_load_store_generator(statement s, const char *module_name)
Generate a communication around a statement instead of plain memory access if it is a call to a funct...
Definition: kernels.c:66
bool kernel_load_store(const char *module_name)
Generate malloc/copy-in/copy-out on the call sites of this module.
Definition: kernels.c:143
static bool kernel_load_store_engine(const char *module_name, const string enginerc)
run kernel load store using either region or effect engine
Definition: kernels.c:93
static bool do_kernelize(statement s, entity loop_label)
create a statement eligible for outlining into a kernel #1 find the loop flagged with loop_label #2 m...
Definition: kernels.c:162
bool bootstrap_kernels(const string module_name)
Definition: kernels.c:297
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define pips_user_error
Definition: misc-local.h:147
string user_request(const char *,...)
#define same_string_p(s1, s2)
int nb_nodes
The timing function.
Definition: prgm_mapping.c:101
const char * get_string_property_or_ask(const char *, const char[])
static const char * prefix
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define make_statement_list(stats...)
easy list constructor
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
void RemoveLocalEntityFromDeclarations(entity, entity, statement)
Definition: variable.c:120
entity find_label_entity(const char *, const char *)
util.c
Definition: util.c:43
#define loop_body(x)
Definition: ri.h:1644
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define loop_execution(x)
Definition: ri.h:1648
#define instruction_loop_p(x)
Definition: ri.h:1518
#define call_function(x)
Definition: ri.h:709
#define callees_callees(x)
Definition: ri.h:675
#define instruction_loop(x)
Definition: ri.h:1520
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define statement_label(x)
Definition: ri.h:2450
#define entity_undefined_p(x)
Definition: ri.h:2762
#define execution_sequential_p(x)
Definition: ri.h:1208
#define loop_label(x)
Definition: ri.h:1646
#define loop_locals(x)
Definition: ri.h:1650
#define statement_instruction(x)
Definition: ri.h:2458
#define loop_range(x)
Definition: ri.h:1642
#define loop_index(x)
Definition: ri.h:1640
char * strdup()
void module_to_value_mappings(entity m)
void module_to_value_mappings(entity m): build hash tables between variables and values (old,...
Definition: mappings.c:624
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
statement loop_strip_mine(statement loop_statement, int chunk_size, int chunk_number)
loop_strip_mine():
Definition: strip_mine.c:64
void free_value_mappings(void)
Normal call to free the mappings.
Definition: value.c:1212