PIPS
mpi_generation.c
Go to the documentation of this file.
1 #ifdef HAVE_CONFIG_H
2  #include "pips_config.h"
3 #endif
4 
5 
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include "boolean.h"
10 #include <stdbool.h>
11 
12 #include "genC.h"
13 #include "linear.h"
14 #include "ri.h"
15 #include "c_syntax.h"
16 #include "effects.h"
17 #include "database.h"
18 #include "misc.h"
19 #include "text.h"
20 #include "text-util.h"
21 #include "ri-util.h"
22 #include "prettyprint.h"
23 #include "effects-util.h"
24 #include "accel-util.h"
25 
26 #include "effects-generic.h"
27 #include "effects-simple.h"
28 
29 #include "pipsdbm.h"
30 #include "resources.h"
31 #include "control.h"
32 #include "conversion.h"
33 #include "properties.h"
34 #include "transformations.h"
35 
36 #include "effects-convex.h"
37 #include "genC.h"
38 #include "syntax.h" // for ImplicitType
39 #include "bootstrap.h"
40 
41 #include "complexity_ri.h"
42 #include "dg.h"
43 
44 /* Instantiation of the dependence graph: */
47 #include "graph.h"
48 #include "ricedg.h"
49 #include "chains.h"
50 #include "task_parallelization.h"
51 
52 /* ImplicitType uses data structures of the Fortran parser. It may
53  * fail because these data structures are not initialized, or return
54  * unexpected results if a Fortran IMPLICIT statement has been
55  * recently parsed.
56  */
57 #define FortranImplicitType(x) \
58  ImplicitType(x)
59 
62 
63 static bool com_statement_p(statement s)
64 {
65  if(statement_loop_p(s)){
67  return com_statement_p(body);
68  }
69  else{
73  }
74 }
75 
77 {
78  list args = NIL, list_stmts = NIL;
80  expression dest = EXPRESSION(CAR(lexpr));
81  expression size = int_to_expression(1);
83  entity name;
85  name = make_constant_entity("MPI_Isend",is_basic_string, 100);
87  args = CONS(EXPRESSION, make_address_of_expression(exp_req), args);
88  tag = copy_expression(dest);
89  }
90  else{
91  name = make_constant_entity("MPI_Recv",is_basic_string, 100);
93  args = CONS(EXPRESSION, make_address_of_expression(exp_st), args);
95  }
96  args = CONS(EXPRESSION, make_entity_expression(make_constant_entity("MPI_COMM_WORLD", is_basic_string, 100), NIL), args);
97  args = CONS(EXPRESSION, tag, args);
98  args = CONS(EXPRESSION, dest, args);
99  expression expr = EXPRESSION(CAR(CDR(lexpr)));
101  switch(basic_tag(bas)){
102  case is_basic_int:
104  break;
105  case is_basic_float:
107  break;
108  default:
109  pips_user_warning("type not handled yet in MPI\n");
110  break;
111  }
112  args = CONS(EXPRESSION, size, args);
113  args = CONS(EXPRESSION, make_address_of_expression(expr), args);
120  com_call,
122  list_stmts = CONS(STATEMENT, st, list_stmts);
127  return;
128 }
129 
141  test new_test = make_test( test_condition,
142  st,
145  statement_instruction(stmt) = inst;
149  return;
150 }
151 
152 /* nesting_level is used to generate only a flat MPI (nesting_level = 1)
153  * hierarchical mpi is not implemented yet (nesting_level = 2)*/
154 static int gen_mpi(statement stmt, int nesting_level){
156  switch(synchronization_tag(sync)){
158  nesting_level = (nesting_level == 0)? 1 : ((nesting_level == 1) ? 2 : nesting_level);
159  gen_if_rank(stmt, sync);
160  break;
162  //MPI_Isend, MPI_recv instructions are sufficient --> no need to
163  //generate MPI_barrier instructions
164  break;
165  default:
166  break;
167  }
168  return nesting_level;
169 }
170 
171 static void gen_flat_mpi(statement stmt, int nesting_level)
172 {
174  switch(instruction_tag(inst))
175  {
177  {
178  int nesting_level_sequence = nesting_level;
179  MAPL(stmt_ptr,
180  {
181  statement st = STATEMENT(CAR( stmt_ptr));
182  if(nesting_level != 2){
183  nesting_level_sequence = gen_mpi(st, nesting_level) ;
184  }
185  gen_flat_mpi(st, nesting_level_sequence);
186  },
187  instruction_block(inst));
188  break;
189  }
190  case is_instruction_test :
191  {
192  test t = instruction_test(inst);
193  int nesting_level_t = gen_mpi(test_true(t), nesting_level);
194  int nesting_level_f = gen_mpi(test_false(t), nesting_level);
195  gen_flat_mpi(test_true(t), nesting_level_t);
196  gen_flat_mpi(test_false(t), nesting_level_f);
197  break;
198  }
199  case is_instruction_loop :
200  {
201  loop l = statement_loop(stmt);
202  statement body = loop_body(l);
203  if(!com_statement_p(body))
204  nesting_level =(nesting_level == 1)? 2:nesting_level;
205  gen_flat_mpi(body, nesting_level);
206  break;
207  }
208  case is_instruction_call:
209  if(com_statement_p(stmt)){
210  if(nesting_level == 2)
212  else
214  }
215  break;
216  default:
217  break;
218  }
219  return;
220 }
221 
222 
223 /* Generate
224  * int rank0;
225  * MPI_Status status0;
226  * MPI_Request *request0;
227  * ierr = MPI_Init( &argc, &argv );
228  * ierr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
229  */
231  list args = NIL, list_stmts = NIL;
233  statement st_body = statement_undefined, st_decls = statement_undefined;
237  {
240  }
242  if(type_undefined_p(entity_type(stat))) {
243  entity_type(stat) = FortranImplicitType(stat);
244  }
246  entity_type(mpi_status) = stat_t;
247 
250  {
253  }
255  if(type_undefined_p(entity_type(req))) {
256  entity_type(req) = FortranImplicitType(req);
257  }
259  entity_type(mpi_request) = req_t;
261 
263  list stmts = sequence_statements(statement_sequence(stmt)), body = NIL, decls = NIL;
264  FOREACH(STATEMENT, s, stmts){
266  decls = CONS(STATEMENT, s, decls);
267  print_statement(s);
268  }
269  else
270  if(!return_statement_p(s))
271  body = CONS(STATEMENT, s, body);
272  else
273  return_st = s;
274  }
275  if(gen_length(body)>0)
276  st_body = make_block_statement(gen_nreverse(body));
277  if(gen_length(decls)>0){
278  st_decls = make_block_statement(gen_nreverse(decls));
279  }
280  }
281  else
282  st_body = stmt;
283  entity name = make_constant_entity("MPI_Init",is_basic_string, 100);
286  st = make_statement(
293  list_stmts = CONS(STATEMENT, st, list_stmts);
294  name = make_constant_entity("MPI_Comm_rank",is_basic_string, 100);
295  args =NIL;
296  args = CONS(EXPRESSION, make_entity_expression(make_constant_entity("MPI_COMM_WORLD", is_basic_string, 100), NIL), args);
298  st = make_statement(
305  list_stmts = CONS(STATEMENT, st, list_stmts);
306  st = make_statement(
313  statement new_s = make_statement(
320  list_stmts = NIL;
321  if(!statement_undefined_p(st_decls))
322  list_stmts = CONS(STATEMENT, st_decls, list_stmts);
323  list_stmts = CONS(STATEMENT, new_s, CONS(STATEMENT, st, list_stmts));
324 
332  return st;
333 }
334 
338  list list_stmts = CONS(STATEMENT, st, CONS(STATEMENT, copy_statement(stmt), NIL));
340  list_stmts = CONS(STATEMENT, return_st, list_stmts);
345  return;
346 }
347 
349 {
351  statement module_stat_i = (statement)db_get_memory_resource(DBR_DISTRIBUTED_SPIRE_CODE, module_name, true);
352  statement module_stat = copy_statement(module_stat_i);
353  set_ordering_to_statement(module_stat);
355  set_current_module_statement(module_stat);
356  init_stmt = mpi_initialize(module_stat, module);
357  gen_flat_mpi(module_stat, 0);
358  mpi_finalize(module_stat);
359  module_reorder(module_stat);
360  gen_consistent_p((gen_chunk*)module_stat);
361  DB_PUT_MEMORY_RESOURCE(DBR_PARALLELIZED_CODE, module_name, module_stat);
365  return true;
366 }
statement return_st
Definition: HBDSC.c:53
instruction copy_instruction(instruction p)
INSTRUCTION.
Definition: ri.c:1115
call make_call(entity a1, list a2)
Definition: ri.c:269
basic make_basic_typedef(entity _field_)
Definition: ri.c:185
storage make_storage_rom(void)
Definition: ri.c:2285
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
entity copy_entity(entity p)
ENTITY.
Definition: ri.c:2521
synchronization make_synchronization_none(void)
Definition: ri.c:2424
sequence make_sequence(list a)
Definition: ri.c:2125
void put_new_typedef(const char *)
This function is used by libraries "step"* and "task_parallelization".
Definition: util.c:1078
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static statement com_call(bool neighbor, list args_com, int k)
entity make_constant_entity(string name, tag bt, size_t size)
For historical reason, call the Fortran version.
Definition: constant.c:301
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
int gen_consistent_p(gen_chunk *obj)
GEN_CONSISTENT_P dynamically checks the type correctness of OBJ.
Definition: genClib.c:2398
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
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
bool native_instruction_p(instruction i, string op_name)
Test if an instruction is a native instruction of the language.
Definition: instruction.c:144
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
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
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool statement_loop_p(statement)
Definition: statement.c:349
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
statement update_statement_instruction(statement, instruction)
Replace the instruction in statement s by instruction i.
Definition: statement.c:3039
bool return_statement_p(statement)
Test if a statement is a C or Fortran "return".
Definition: statement.c:172
statement make_call_statement(string, list, entity, string)
This function is limited to intrinsics calls...
Definition: statement.c:1274
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
#define pips_user_warning
Definition: misc-local.h:146
static void gen_if_rank(statement stmt, synchronization sync)
static int gen_mpi(statement stmt, int nesting_level)
nesting_level is used to generate only a flat MPI (nesting_level = 1) hierarchical mpi is not impleme...
#define FortranImplicitType(x)
ImplicitType uses data structures of the Fortran parser.
static entity mpi_status
static void gen_mpi_send_recv(statement stmt)
static statement mpi_initialize(statement stmt, entity module)
Generate int rank0; MPI_Status status0; MPI_Request *request0; ierr = MPI_Init( &argc,...
dg_vertex_label vertex_label
static bool com_statement_p(statement s)
static void mpi_finalize(statement stmt)
static entity mpi_request
static void gen_flat_mpi(statement stmt, int nesting_level)
dg_arc_label arc_label
Instantiation of the dependence graph:
static statement init_stmt
static entity rank
bool mpi_task_generation(char *module_name)
mpi_generation.c
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
int tag
TAG.
Definition: newgen_types.h:92
#define string_undefined
Definition: newgen_types.h:40
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
static char * module
Definition: pips.c:74
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define RECV_FUNCTION_NAME
#define MPI_STATUS
PI types.
#define EQUAL_OPERATOR_NAME
#define STATEMENT_NUMBER_UNDEFINED
default values
#define MPI_REQUEST
#define is_instruction_block
soft block->sequence transition
#define SEND_FUNCTION_NAME
SPIRE API.
#define instruction_block(i)
#define empty_comments
Empty comments (i.e.
#define MPI_FINALIZE_FUNCTION_NAME
#define make_empty_statement
An alias for make_empty_block_statement.
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity entity_empty_label(void)
Definition: entity.c:1105
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression make_entity_expression(entity e, cons *inds)
Definition: expression.c:176
expression make_address_of_expression(expression e)
generate a newly allocated expression for &(e)
Definition: expression.c:3956
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
basic MakeBasic(int)
END_EOLE.
Definition: type.c:128
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
type MakeTypeVariable(basic, cons *)
BEGIN_EOLE.
Definition: type.c:116
#define loop_body(x)
Definition: ri.h:1644
@ is_basic_string
Definition: ri.h:576
@ is_basic_float
Definition: ri.h:572
@ is_basic_int
Definition: ri.h:571
@ is_synchronization_barrier
Definition: ri.h:2626
@ is_synchronization_spawn
Definition: ri.h:2625
#define synchronization_spawn(x)
Definition: ri.h:2657
#define synchronization_tag(x)
Definition: ri.h:2651
#define test_false(x)
Definition: ri.h:2837
#define statement_synchronization(x)
Definition: ri.h:2466
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define statement_label(x)
Definition: ri.h:2450
#define type_undefined_p(x)
Definition: ri.h:2884
#define entity_undefined
Definition: ri.h:2761
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define statement_extensions(x)
Definition: ri.h:2464
#define test_condition(x)
Definition: ri.h:2833
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
#define call_arguments(x)
Definition: ri.h:711
#define instruction_test(x)
Definition: ri.h:1517
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define storage_undefined_p(x)
Definition: ri.h:2477
#define variable_basic(x)
Definition: ri.h:3120
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
A gen_chunk is used to store every object.
Definition: genC.h:58