PIPS
io-util.c
Go to the documentation of this file.
1 /*
2 
3  $Id: io-util.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* HPFC module by Fabien COELHO
28  */
29 
30 #include "defines-local.h"
31 
32 #include "conversion.h"
33 #include "effects-generic.h"
34 #include "effects-simple.h"
35 #include "effects-convex.h"
36 
37 /************************************************** ONLY_IO MAP DEFINITION */
38 
39 /* this is enough for the distribution purpose, because more clever
40  * analysis would be as checking for the distributablity of the enclosed
41  * code. A distribution code dedicated to IO will be implemented later on.
42  * only io encoding:
43  * 0 - not an IO
44  * 1 - is an IO
45  * 3 - may be considered as an IO along real IO functions...
46  */
47 
48 GENERIC_CURRENT_MAPPING(only_io, bool, statement)
49 
50 static statement_mapping
52 
53 #define Load(stat) \
54  ((bool)(intptr_t) (hash_get(stat_bool_map, stat)))
55 
56 #define Store(stat, val) \
57  (hash_put(stat_bool_map, (void*)stat, (void*) (val)))
58 
59 /* true if the first statement of a block is a host section marker.
60  * looks like a hack. should be managed in directives.c...
61  */
62 static bool
64  list /* of statement */ ls)
65 {
66  if (gen_length(ls)>=1)
67  {
69  if (instruction_call_p(one))
70  return same_string_p
73  }
74 
75  return false;
76 }
77 
78 /* ??? neglect expression side effects...
79  */
81 
83 {
84  error_reset_current_statement_stack();
85 }
86 
87 static void only_io_sequence(sequence q)
88 {
89  intptr_t is_io;
91  is_io=1;
92  else
93  {
94  is_io=3;
95  MAP(STATEMENT, s, is_io = (is_io & Load(s)), sequence_statements(q));
96  }
97 
98  pips_debug(5, "block %p: %"PRIdPTR"\n", q, is_io);
99  Store(current_statement_head(), is_io);
100 }
101 
102 static void only_io_test(test t)
103 {
104  intptr_t is_io=3;
105  is_io = (Load(test_true(t)) & Load(test_false(t)));
106  pips_debug(5, "test %p: %"PRIdPTR"\n", t, is_io);
107  Store(current_statement_head(), is_io);
108 }
109 
110 static void only_io_loop(loop l)
111 {
112  intptr_t is_io = Load(loop_body(l));
113  pips_debug(5, "loop %p: %"PRIdPTR"\n", l, is_io);
114  Store(current_statement_head(), is_io);
115 }
116 
117 static void only_io_call(call c)
118 {
119  entity f = call_function(c);
120  intptr_t is_io = entity_continue_p(f)? 3:
121  io_intrinsic_p(f) || /* Fortran IO intrinsics */
122  hpfc_special_io(f) || /* declared with FCD */
123  hpfc_io_like_function(f);/* runtime managed */
124 
125  pips_debug(5, "call %p (%s): %"PRIdPTR"\n", c, entity_name(f), is_io);
126  Store(current_statement_head(), is_io);
127 }
128 
130 {
131  intptr_t is_io = 3;
133  list blocks = NIL;
134 
135  CONTROL_MAP(ct, is_io = is_io & Load(control_statement(ct)), c, blocks);
137  pips_debug(5, "unstructured %p: %"PRIdPTR"\n", u, is_io);
138  Store(current_statement_head(), (void*)is_io);
139 }
140 
141 static statement_mapping
143  statement program,
144  statement_mapping map)
145 {
146  stat_bool_map = map;
147 
148  make_current_statement_stack();
149  gen_multi_recurse(program,
150  statement_domain, current_statement_filter, current_statement_rewrite,
157  NULL);
158  free_current_statement_stack();
159  return stat_bool_map;
160 }
161 
162 void
164  statement program)
165 {
166  debug_on("HPFC_IO_DEBUG_LEVEL");
168  debug_off();
169 }
170 
171 
172 
173 /********************************************* GENERATION OF IO STATEMENTS */
174 
175 /* T_LID=CMP_LID(pn, pi...)
176  * ? init buffer...
177  * / CALL (type) PACK...
178  * CALL HPFC {SND TO,RCV FROM} NODE(T_LID)
179  * / CALL (type) UPCK...
180  */
182  entity array,
183  entity proc,
184  bool send)
185 {
186  entity ld;
187  expression lid;
188  statement cmp_lid, comm, pack;
189  list /* statement */ lp, ls;
190 
192  lid = entity_to_expression(ld);
193  cmp_lid = hpfc_compute_lid(ld, proc, (entity (*)())get_ith_processor_dummy, NULL);
194 
195  lp = CONS(STATEMENT, cmp_lid, NIL);
196 
197  if (!send)
198  lp = CONS(STATEMENT, hpfc_buffer_initialization(false, false, false),
199  lp);
200 
202  send? HPFC_sH2N: HPFC_rN2H), CONS(EXPRESSION, lid, NIL));
203 
205 
206  if (send)
207  ls = CONS(STATEMENT, pack, CONS(STATEMENT, comm, NIL));
208  else
209  ls = CONS(STATEMENT, comm, CONS(STATEMENT, pack, NIL));
210 
211  return make_block_statement(gen_nconc(lp, ls));
212 }
213 
214 /* ! init buffer
215  * CALL HPFC {RCV FROM HOST, NCAST}
216  * CALL (type) BUFFER UNPACK
217  */
219  entity array,
220  bool cast) /* from host */
221 {
222  return make_block_statement(
223  CONS(STATEMENT, hpfc_buffer_initialization(false, false, false),
227  NIL))));
228 }
229 
230 /* PVM_SEND(HOST_TID, HOST SND CHANNEL, INFO)
231  * HOST SND CHANNEL += 2
232  */
234 {
235  return make_block_statement(
239  NIL)));
240 }
241 
242 /* static statement hpfc_hcast()
243  *
244  * PVM_CAST(NBTASKS, NODETIDS, MCASTHOST, INFO)
245  * MCASTHOST = MCASTHOST + 2
246  */
248 {
249  return make_block_statement(
251  CONS(STATEMENT,
253  NIL)));
254 }
255 
256 #define GENERATION(NAME, COLLECT, UPDATE)\
257 static statement NAME(array, move) entity array; tag move;\
258 {pips_assert("valid move", \
259  move==is_movement_collect || move==is_movement_update);\
260  return((move==is_movement_collect) ? (COLLECT) : (UPDATE));}
261 
262 GENERATION(node_pre_io,
263  hpfc_buffer_initialization(true, false, true),
264  hpfc_nrecv(array, false))
265 GENERATION(node_in_io,
268 GENERATION(node_post_io,
269  hpfc_nsend(array),
271 GENERATION(host_pre_io,
274 GENERATION(host_in_io,
277 GENERATION(host_post_io,
280 
281 /* generate_io_statements_for_distributed_arrays
282  *
283  * ??? the variables are not generated in the right module
284  *
285  * code to be generated:
286  *
287  * Host:
288  *
289  * [ IF condition then ]
290  * DO host_proc_loop
291  * host_pre_io
292  * DO host_scan_loop
293  * host_deduce
294  * host_in_io
295  * ENDDO
296  * host_post_io
297  * ENDDO
298  * [ ENDIF ]
299  *
300  * Node:
301  *
302  * [ IF condition then ]
303  * node_defproc
304  * [ IF proc_cond then ]
305  * node_pre_io
306  * DO node_scan_loop
307  * node_deduce
308  * node_in_io
309  * ENDDO
310  * node_post_io
311  * [ ENDIF ]
312  * [ ENDIF ]
313  *
314  */
316  entity array, tag move,
317  Psysteme condition, Psysteme proc_echelon, Psysteme tile_echelon,
318  _UNUSED_ list parameters, list processors, list scanners, list rebuild,
319  statement *psh, statement *psn)
320 {
321  string comment;
322  entity
323  proc = array_to_processors(array),
325  Psysteme
326  /* proc_cond computation:
327  * well, it may have been kept before the new loop bound computation?
328  */
329  proc_decl = entity_to_declaration_constraints(proc, 2),
330  proc_cond_tmp = sc_dup(proc_echelon),
331  proc_cond = (sc_nredund(&proc_cond_tmp),
332  extract_nredund_subsystem(proc_cond_tmp, proc_decl));
333  statement
334  h_cont = make_empty_statement(),
335  n_cont = make_empty_statement(),
336  node_tmp = statement_undefined,
338  node_deduce = generate_deducables(rebuild),
339  host_deduce = generate_deducables(rebuild),
340  h_pre = host_pre_io(array, move),
341  h_in = host_in_io(array, move),
342  h_post = host_post_io(array, move),
343  n_pre = node_pre_io(array, move),
344  n_in = node_in_io(array, move),
345  n_post = node_post_io(array, move),
346  host_scan_loop =
348  (tile_echelon,
349  scanners,
350  make_block_statement(CONS(STATEMENT, host_deduce,
351  CONS(STATEMENT, h_in,
352  NIL))),
353  divide),
354  host_proc_loop =
356  (proc_echelon,
357  processors,
359  CONS(STATEMENT, host_scan_loop,
360  CONS(STATEMENT, h_post,
361  NIL)))),
362  divide),
363  node_scan_loop =
365  (tile_echelon,
366  scanners,
367  make_block_statement(CONS(STATEMENT, node_deduce,
368  CONS(STATEMENT, n_in,
369  NIL))),
370  divide);
371 
372  *psh = make_block_statement(
373  CONS(STATEMENT, generate_optional_if(condition, host_proc_loop),
374  CONS(STATEMENT, h_cont, NIL)));
375 
376  node_tmp =
378  CONS(STATEMENT, node_scan_loop,
379  CONS(STATEMENT, n_post,
380  NIL))));
381  *psn = make_block_statement(
383  (condition, make_block_statement(CONS(STATEMENT, node_defproc,
384  CONS(STATEMENT,
385  generate_optional_if(proc_cond, node_tmp), NIL)))),
386  CONS(STATEMENT, n_cont, NIL)));
387 
388  sc_rm(proc_cond_tmp), sc_rm(proc_cond);
389 
390  comment = strdup(concatenate("! ",
391  movement_update_p(move) ? "updating" : "collecting",
392  " distributed variable ",
393  entity_local_name(array), "\n", NULL));
394 
397  free(comment);
398 
399  comment = strdup(concatenate("! end of ",
400  movement_update_p(move) ? "update" : "collect",
401  "\n", NULL));
403  /* Do not forget to move forbidden information associated with
404  block: */
406  free(comment);
407 
408  DEBUG_STAT(5, "Host", *psh);
409  DEBUG_STAT(5, "Node", *psn);
410 }
411 
412 /* generate_io_statements_for_shared_arrays
413  *
414  * code to be generated:
415  *
416  * Host:
417  *
418  * [ IF condition then ]
419  * init_send
420  * DO scanners
421  * rebuild
422  * pack
423  * ENDDO
424  * host_cast
425  * [ ENDIF ]
426  *
427  * Node:
428  *
429  * [ IF condition then ]
430  * receive_hcast
431  * DO scanners
432  * rebuild
433  * unpack
434  * ENDDO
435  * [ ENDIF ]
436  *
437  */
439  entity array,
440  tag move,
441  Psysteme condition,
442  Psysteme echelon,
443  _UNUSED_ list parameters,
444  list scanners,
445  list rebuild,
446  statement *psh,
447  statement *psn)
448 {
450  string comment;
451  statement
452  h_cont = make_empty_statement(),
453  n_cont = make_empty_statement(),
454  h_pre = hpfc_buffer_initialization(true, false, true),
455  h_rebuild = generate_deducables(rebuild),
456  h_pack = hpfc_buffer_packing(array, (entity (*)())get_ith_array_dummy, true),
457  h_cast = hpfc_hcast(array),
458  n_rcv = hpfc_nrecv(array, true),
459  n_rebuild = generate_deducables(rebuild),
460  n_unpack = hpfc_buffer_packing(array, (entity (*)())get_ith_local_dummy, false),
461  h_scan = systeme_to_loop_nest
462  (echelon,
463  scanners,
465  CONS(STATEMENT, h_pack,
466  NIL))),
467  divide),
468  n_scan = systeme_to_loop_nest
469  (echelon,
470  scanners,
472  CONS(STATEMENT, n_unpack,
473  NIL))),
474  divide);
475 
476  pips_assert("update", movement_update_p(move));
477 
478  *psh = make_block_statement(
480  (condition, make_block_statement(CONS(STATEMENT, h_pre,
481  CONS(STATEMENT, h_scan,
482  CONS(STATEMENT, h_cast,
483  NIL))))),
484  CONS(STATEMENT, h_cont, NIL)));
485 
486  *psn = make_block_statement(
488  (condition, make_block_statement(CONS(STATEMENT, n_rcv,
489  CONS(STATEMENT, n_scan,
490  NIL)))),
491  CONS(STATEMENT, n_cont, NIL)));
492 
493  /* some comments are generated to help understand the code
494  */
495  comment = strdup(concatenate("! updating shared variable ",
496  entity_local_name(array), "\n", NULL));
499  free(comment);
500  insert_comments_to_statement(h_cont, "! end of update\n");
501  insert_comments_to_statement(n_cont, "! end of update\n");
502 }
503 
504 /* that is all
505  */
#define divide(a, b)
Psysteme entity_to_declaration_constraints(entity e, tag what)
gives back the constraints due to the declarations.
Definition: build-system.c:285
static list blocks
lisp of loops
statement systeme_to_loop_nest(Psysteme, list, statement, entity)
sc is used to generate the loop nest bounds for variables vars.
statement generate_optional_if(Psysteme, statement)
statement generate_optional_if(sc, stat)
static void comment(string_buffer code, spoc_hardware_type hw, dagvtx v, int stage, int side, bool flip)
Definition: freia_spoc.c:52
statement hpfc_compute_lid(entity lid, entity proc, entity(*creation)(), entity array)
statement st_compute_lid(proc)
statement generate_deducables(list le)
statement generate_deducables(list le)
Definition: generate-util.c:83
statement define_node_processor_id(entity proc, entity(*creation)(int))
builds a statement VAR_i = MYPOS(i, proc_number) // i=1 to proc dimension
Definition: generate-util.c:49
statement hpfc_buffer_packing(entity array, entity(*creation)(), bool pack)
array(creation) = buffer(current++) or reverse assignment...
statement hpfc_buffer_initialization(bool is_send, _UNUSED_ bool is_lazy, bool job_was_done)
statement hpfc_packing_of_current__buffer(entity array, bool pack)
CALL (pvmtype) HPFC {,UN}PACK.
void free(void *)
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
void insert_comments_to_statement(statement, const char *)
Insert a comment string (if non empty) at the beginning of the comments of a statement.
Definition: statement.c:1916
#define array_to_processors(array)
#define IDIVIDE
#define HPFC_rN2H
#define HPFC_HCAST
host/node communications
#define HPFC_rH2N
#define DEBUG_STAT(D, W, S)
#define movement_update_p(t)
#define T_LID
Variables.
#define HPFC_sH2N
#define HPFC_sN2H
#define HPFC_NCAST
bool hpfc_special_io(entity f)
Definition: hpfc.c:77
void generate_io_statements_for_distributed_arrays(entity, tag, Psysteme, Psysteme, Psysteme, list, list, list, list, statement *, statement *)
void set_only_io_map(statement_mapping)
entity hpfc_name_to_entity(const char *)
Definition: run-time.c:817
entity get_ith_array_dummy(int)
statement hpfc_make_call_statement(entity, list)
statement hpfc_make_call_statement(e, l) generate a call statement to function e, with expression lis...
Definition: run-time.c:318
entity get_ith_processor_dummy(int)
entity get_ith_local_dummy(int)
bool hpfc_io_like_function(entity)
Definition: run-time.c:836
static statement hpfc_nsend(entity array)
PVM_SEND(HOST_TID, HOST SND CHANNEL, INFO) HOST SND CHANNEL += 2.
Definition: io-util.c:233
void hpfc_io_util_error_handler()
??? neglect expression side effects...
Definition: io-util.c:82
void generate_io_statements_for_shared_arrays(entity array, tag move, Psysteme condition, Psysteme echelon, _UNUSED_ list parameters, list scanners, list rebuild, statement *psh, statement *psn)
generate_io_statements_for_shared_arrays
Definition: io-util.c:438
#define Store(stat, val)
Definition: io-util.c:56
static void only_io_call(call c)
Definition: io-util.c:117
static void only_io_sequence(sequence q)
Definition: io-util.c:87
static statement_mapping stat_bool_map
HPFC module by Fabien COELHO.
Definition: io-util.c:51
#define Load(stat)
Definition: io-util.c:53
static statement hpfc_hmessage(entity array, entity proc, bool send)
T_LID=CMP_LID(pn, pi...) ? init buffer...
Definition: io-util.c:181
static statement_mapping only_io_mapping(statement program, statement_mapping map)
Definition: io-util.c:142
static void only_io_test(test t)
Definition: io-util.c:102
#define GENERATION(NAME, COLLECT, UPDATE)
Definition: io-util.c:256
static bool host_section_p(list ls)
true if the first statement of a block is a host section marker.
Definition: io-util.c:63
void only_io_mapping_initialize(statement program)
Definition: io-util.c:163
static void only_io_loop(loop l)
Definition: io-util.c:110
static statement hpfc_hcast(entity array)
static statement hpfc_hcast()
Definition: io-util.c:247
static void only_io_unstructured(unstructured u)
Definition: io-util.c:129
static statement hpfc_nrecv(entity array, bool cast)
! init buffer CALL HPFC {RCV FROM HOST, NCAST} CALL (type) BUFFER UNPACK
Definition: io-util.c:218
#define debug_on(env)
Definition: misc-local.h:157
#define _UNUSED_
Definition: misc-local.h:232
#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_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define MAKE_STATEMENT_MAPPING()
Definition: newgen-local.h:43
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define GENERIC_CURRENT_MAPPING(name, result, type)
#define DEFINE_LOCAL_STACK(name, type)
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
#define same_string_p(s1, s2)
int tag
TAG.
Definition: newgen_types.h:92
#define true
Definition: newgen_types.h:81
#define false
Definition: newgen_types.h:80
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define HPF_PREFIX
moved here because needed by syntax:-(
#define HOSTSECTION_SUFFIX
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define make_empty_statement
An alias for make_empty_block_statement.
bool entity_continue_p(entity f)
Definition: entity.c:1731
bool io_intrinsic_p(entity e)
rue is a statement s is an io intrinsic
Definition: entity.c:1655
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
#define loop_body(x)
Definition: ri.h:1644
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define call_function(x)
Definition: ri.h:709
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define test_false(x)
Definition: ri.h:2837
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_name(x)
Definition: ri.h:2790
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define instruction_call_p(x)
Definition: ri.h:1527
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define control_statement(x)
Definition: ri.h:941
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
Psysteme extract_nredund_subsystem(Psysteme s1, Psysteme s2)
Psysteme extract_nredund_subsystem(s1, s2) Psysteme s1, s2;.
char * strdup()
static statement current_statement
static entity array
#define intptr_t
Definition: stdint.in.h:294
The structure used to build lists in NewGen.
Definition: newgen_list.h:41