Sélectionner une révision Git
-
Maxime DESMARCHELIER a rédigéMaxime DESMARCHELIER a rédigé
mpi_collective_pass.cpp 5,17 Kio
// dependance of context.h
#include <gcc-plugin.h>
// 'g' global variable
#include <context.h>
// dependance of gimple.h
#include <tree.h>
// dependance of gimple-iterator.h
#include <gimple.h>
// gsi
#include <gimple-iterator.h>
// our pass
#include "mpi_collective.hpp"
// Definitions
const pass_data my_pass_data =
{
GIMPLE_PASS, /* type */
"MPI COLLECTIVE", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_OPTIMIZE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
// Class functions
pass_mpi_collective::pass_mpi_collective(gcc::context *ctxt)
: opt_pass(my_pass_data, ctxt)
{
for (int i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i)
{
collective_max_rank[i] = 0;
}
}
pass_mpi_collective *pass_mpi_collective::clone()
{
return new pass_mpi_collective(g);
}
bool pass_mpi_collective::gate(function *fun)
{
//printf("In gate of: %s\n", fndecl_name(fun->decl));
printf("In gate of: %s\n", function_name(fun));
//printf("In gate of: %s\n", current_function_name());
return true;
}
unsigned int pass_mpi_collective::execute(function *fun)
{
// need because pass objectis reused
for (int i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i)
{
collective_max_rank[i] = 0;
}
printf("In execute of: %s\n", function_name(fun));
//print_tree(fun);
split_blocks(fun);
//printf("\t--------------------------[split]---------------------------\n");
//print_tree(fun);
alloc_bb_aux(fun);
alloc_edge_aux(fun);
calc_dom_data();
label_collec(fun);
label_dom(fun);
label_post_dom(fun);
label_dom_front(fun);
label_post_dom_front(fun);
mark_edge(fun);
rank_collective(fun);
//better_rank_collective(fun);
//bitmap_head pdbitmap = get_set_mpi_coll_rank(fun, 2, MPI_BARRIER);
//debug_bitmap(&pdbitmap);
//bitmap_head pdf = get_frontier_from_pds(fun, &pdbitmap);
//debug_bitmap(&pdf);
cfgviz_dump(fun, "_split");
printf("[][][][][][][][][][]\n");
raise_warning_if_mpi_wrong(fun);
free_dom_data();
free_bb_aux(fun);
free_edge_aux(fun);
return 0;
}
// MPI function & collectives detections
bool pass_mpi_collective::is_func(gimple *stmt)
{
return is_gimple_call(stmt);
}
bool pass_mpi_collective::__is_mpi_func(gimple *stmt)
{
return strncmp(fndecl_name(gimple_call_fndecl(stmt)), "MPI_", 4) == 0;
}
bool pass_mpi_collective::is_mpi_func(gimple *stmt)
{
return is_func(stmt) && __is_mpi_func(stmt);
}
mpi_collective_code pass_mpi_collective::__is_mpi_collec(gimple *stmt)
{
size_t i;
const char *callee_name;
callee_name = fndecl_name(gimple_call_fndecl(stmt));
for (i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i)
{
if (strcmp(mpi_collective_name[i], callee_name) == 0)
{
return (enum mpi_collective_code) i;
}
}
return LAST_AND_UNUSED_MPI_COLLECTIVE_CODE;
}
mpi_collective_code pass_mpi_collective::is_mpi_collec(gimple *stmt)
{
if (!is_mpi_func(stmt))
{
return LAST_AND_UNUSED_MPI_COLLECTIVE_CODE;
}
return __is_mpi_collec(stmt);
}
// print bb & statment with mpi collectives
void pass_mpi_collective::print_tree(function *fun)
{
basic_block bb;
gimple_stmt_iterator gsi;
gimple *stmt;
//size_t line;
FOR_EACH_BB_FN(bb, fun)
{
printf("\tBasic block: %d\n", bb->index);
for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
{
stmt = gsi_stmt(gsi);
//line = gimple_lineno(stmt);
//printf("\tstatement at line = %lu\n", line);
if (is_func(stmt))
{
printf("\t\tStatement is a function call (%s)\n",
fndecl_name(gimple_call_fndecl(stmt)));
if (__is_mpi_func(stmt))
{
printf("\t\t\tStatement is a MPI function call (%s)\n",
fndecl_name(gimple_call_fndecl(stmt)));
if (__is_mpi_collec(stmt)
!= LAST_AND_UNUSED_MPI_COLLECTIVE_CODE)
{
printf("\t\t\t\tStatement is a MPI collective (%s)\n",
fndecl_name(gimple_call_fndecl(stmt)));
}
}
}
}
}
}
// split blocks according to MPI collectives
void pass_mpi_collective::split_blocks(function *fun)
{
basic_block bb;
gimple_stmt_iterator gsi;
gimple *stmt;
gimple *prev_stmt;
size_t nb_collective;
bool split;
FOR_EACH_BB_FN(bb, fun)
{
nb_collective = 0;
stmt = NULL;
split = false;
for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi) && !split; gsi_next(&gsi))
{
prev_stmt = stmt;
stmt = gsi_stmt(gsi);
if (is_mpi_collec(stmt) != LAST_AND_UNUSED_MPI_COLLECTIVE_CODE)
{
++nb_collective;
}
if (nb_collective >= 2)
{
split_block(bb, prev_stmt);
split = true;
//The inner for doesn't stop naturally, whereas the
//FOR_EACH_BB_FN *will* iterate on the new bb we just split.
//hence the split=true
}
}
}
}
// Label Basic Block with the MPI collectives they are using.
void pass_mpi_collective::label_collec(function *fun)
{
basic_block bb;
gimple_stmt_iterator gsi;
gimple *stmt;
mpi_collective_code mpi_code;
FOR_ALL_BB_FN(bb, fun)
{
((bb_data *) bb->aux)->mpi_code = LAST_AND_UNUSED_MPI_COLLECTIVE_CODE;
for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
{
stmt = gsi_stmt(gsi);
mpi_code = is_mpi_collec(stmt);
if (mpi_code != LAST_AND_UNUSED_MPI_COLLECTIVE_CODE)
{
((bb_data *) bb->aux)->mpi_code = mpi_code;
}
}
}
}