diff --git a/Makefile b/Makefile index 854139eaf8c04b5b4b7e7751ce0084229f7c6170..c8a0838910f6061f84fdf1bbe0d9a635a02ec6ba 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,11 @@ TESTSRCD=$(SRCD)/test DOTD=dot # Files -SRCS=$(notdir $(wildcard ($(SRCD)/*.cpp)) +SRCS=$(notdir $(wildcard $(SRCD)/*.cpp)) OBJS=$(addprefix $(OBJD)/, $(SRCS:cpp=o)) + .PHONY: all all: $(MAKE) plugin @@ -67,7 +68,7 @@ $(TESTD)/%: $(TESTSRCD)/%.c $(OBJD)/%.o: $(SRCD)/%.cpp $(CXX) $(FLAGS) $(PLUGIN_INCLUDE) -c $^ -o $@ -$(LIBD)/libplugin.so: $(OBJD)/plugin.o $(OBJD)/pass_mpi_collective.o +$(LIBD)/libplugin.so: $(OBJS) $(CXX) $(FLAGS) $(LDFLAGS) $^ -o $@ # removing test scince plugin was rebuild rm -rf $(TESTD) diff --git a/include/pass_mpi_collective.hpp b/include/mpi_collective.hpp similarity index 66% rename from include/pass_mpi_collective.hpp rename to include/mpi_collective.hpp index a433ea683edebe073c88ab0863b969dff9a44f1c..b66fda1017ae0796108a845d43248dbec82c99c6 100644 --- a/include/pass_mpi_collective.hpp +++ b/include/mpi_collective.hpp @@ -53,72 +53,90 @@ class pass_mpi_collective : public opt_pass { public: + // maximum rank for each collective in the current cfg. int collective_max_rank[LAST_AND_UNUSED_MPI_COLLECTIVE_CODE]; + // + // mpi collective pass + // + // constructor & clone function pass_mpi_collective(gcc::context *ctxt); pass_mpi_collective *clone(); - + // pass functions bool gate(function *fun); unsigned int execute(function *fun); - - void print_tree(function *fun); - - // MPI function / collectives detections + // functions used to detect normal functions, + // mpi functions & mpi collectives. bool is_func(gimple *stmt); bool __is_mpi_func(gimple *stmt); bool is_mpi_func(gimple *stmt); mpi_collective_code __is_mpi_collec(gimple *stmt); mpi_collective_code is_mpi_collec(gimple *stmt); - + // print basic block with mpi collective + void print_tree(function *fun); // split blocks according to mpi collectives void split_blocks(function *fun); + // label blocks according to mpi colelctives + void label_collec(function *fun); - // gestions des aux + // + // mpi collective graph utils + // + // allocate, free & reset data structure that are used in graph parkour + // in node and edge of the graph. void alloc_bb_aux(function *fun); - void label_collec(function *fun); void free_bb_aux(function *fun); - - // calculate dominances - void label_dom(function *fun); - void label_dom_front(function *fun); - void free_dom_data(); - - // parkour de graph void reset_bb_mark(function *fun); void alloc_edge_aux(function *fun); void free_edge_aux(function *fun); - - // loop detection + // loop detection algorithms void __mark_edge_naif(function *fun); void __mark_edge_naif(basic_block bb); - void __mark_edge(function *fun); + void __mark_edge_test(function *fun); void mark_edge(function *fun); void mark_edge(basic_block bb); - // rank definition - void rank_collective(function *fun); - void __rank_collective(basic_block bb); - - void better_rank_collective(function *fun); - int __better_rank_collective(basic_block bb, - mpi_collective_code mpi_code, int rank); - - //post-dom set of same-rank collectives - void get_mpi_coll_rank( - function *fun, int rank, int mpi_code, bitmap mpi_coll); + // + // mpi collective dominance + // + // alloc & free dominance info in gcc + void calc_dom_data(); + void free_dom_data(); + // label graph with dominance, post dominance, dominance frontier + // and post dominance frontier + void label_dom(function *fun); + void label_post_dom(function *fun); + void label_dom_front(function *fun); + void label_post_dom_front(function *fun); + // calculate post dominance of a set of nodes in a bitmap void __is_post_dom_bitmap( function *fun, basic_block bb, bitmap nodes, bitmap pds); void get_post_dom_bitmap(function *fun, bitmap nodes, bitmap pds); - - //post-dom set frontier + // calculate post dominance frontier of a set of nodes in a bitmap void get_post_dom_frontier(function *fun, bitmap pds, bitmap pdf); - //err warning + // + // mpi collective warnings + // + // functions that rank mpi collectives + void rank_collective(function *fun); + void __rank_collective(basic_block bb); + void better_rank_collective(function *fun); + int __better_rank_collective( + basic_block bb, mpi_collective_code mpi_code, int rank); + // function that calculate agregate a mpi collective + // with the same rank in a bitmap + void get_mpi_coll_rank( + function *fun, int rank, int mpi_code, bitmap mpi_coll); + // raise warnings when mpi collective are badly uses void raise_warning_if_mpi_wrong(function *fun); - // GRAPHVIZ - char *cfgviz_generate_filename(function *fun, - const char *suffix); + // + // mpi collective graphviz + // + char *cfgviz_generate_filename(function *fun, const char *suffix); void cfgviz_internal_dump(function *fun, FILE *out); void cfgviz_dump(function *fun, const char *suffix); + }; + diff --git a/src/mpi_collective_dominance.cpp b/src/mpi_collective_dominance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87369883d0f7dff21f8af56a8911066523c3cbb1 --- /dev/null +++ b/src/mpi_collective_dominance.cpp @@ -0,0 +1,245 @@ +#include <gcc-plugin.h> + +#include "mpi_collective.hpp" + +// calculate dominances and post dominances informations in gcc. +void pass_mpi_collective::calc_dom_data() +{ + calculate_dominance_info(CDI_DOMINATORS); + calculate_dominance_info(CDI_POST_DOMINATORS); +} + +// free dominances and post dominancse informations in gcc. +void pass_mpi_collective::free_dom_data() +{ + free_dominance_info(CDI_DOMINATORS); + free_dominance_info(CDI_POST_DOMINATORS); +} + +// set dominances informations from gcc in bb. +void pass_mpi_collective::label_dom(function *fun) +{ + basic_block bb; + auto_vec<basic_block> dom_gccvec; + size_t size_dom; + + FOR_ALL_BB_FN(bb, fun) + { + bb_data *data = ((bb_data *) bb->aux); + + dom_gccvec = get_all_dominated_blocks(CDI_DOMINATORS, bb); + size_dom = dom_gccvec.length(); + for (size_t i = 0; i < size_dom; ++i) + { + if (dom_gccvec[i]->index != bb->index) + { + bitmap_set_bit(&data->dom, dom_gccvec[i]->index); + } + } + } +} + +// set post dominances informations from gcc in bb. +void pass_mpi_collective::label_post_dom(function *fun) +{ + basic_block bb; + auto_vec<basic_block> post_dom_gccvec; + size_t size_post_dom; + + FOR_ALL_BB_FN(bb, fun) + { + bb_data *data = ((bb_data *) bb->aux); + + post_dom_gccvec = get_all_dominated_blocks(CDI_POST_DOMINATORS, bb); + size_post_dom = post_dom_gccvec.length(); + for (size_t i = 0; i < size_post_dom; ++i) + { + if (post_dom_gccvec[i]->index != bb->index) + { + bitmap_set_bit(&data->post_dom, post_dom_gccvec[i]->index); + } + } + } +} + +// calculate dominances frontiers informations +// and save them in bb. +void pass_mpi_collective::label_dom_front(function *fun) +{ + edge p; + edge_iterator ei; + basic_block bb; + basic_block dom_bb; + basic_block runner; + bb_data *data; + + FOR_EACH_BB_FN(bb, fun) + { + if (EDGE_COUNT(bb->preds) < 2) + { + continue; + } + dom_bb = get_immediate_dominator(CDI_DOMINATORS, bb); + FOR_EACH_EDGE(p, ei, bb->preds) + { + runner = p->src; + if (runner == ENTRY_BLOCK_PTR_FOR_FN(fun)) + { + continue; + } + while (runner != dom_bb) + { + data = (bb_data *) runner->aux; + if (bitmap_bit_p(&data->dom_front, bb->index)) + { + break; + } + bitmap_set_bit(&data->dom_front, bb->index); + runner = get_immediate_dominator(CDI_DOMINATORS, runner); + } + } + } +} + +// calculate post dominances frontiers informations +// and save them in bb. +void pass_mpi_collective::label_post_dom_front(function *fun) +{ + edge p; + edge_iterator ei; + basic_block bb; + basic_block dom_bb; + basic_block runner; + bb_data *data; + + FOR_EACH_BB_FN(bb, fun) + { + if (EDGE_COUNT(bb->succs) < 2) + { + continue; + } + dom_bb = get_immediate_dominator(CDI_POST_DOMINATORS, bb); + FOR_EACH_EDGE(p, ei, bb->succs) + { + runner = p->dest; + if (runner == EXIT_BLOCK_PTR_FOR_FN(fun)) + { + continue; + } + while (runner != dom_bb) + { + data = (bb_data *) runner->aux; + if (bitmap_bit_p(&data->post_dom_front, bb->index)) + { + break; + } + bitmap_set_bit(&data->post_dom_front, bb->index); + runner = get_immediate_dominator(CDI_POST_DOMINATORS, runner); + } + } + } +} + +// calculate post dominances of a set of node in bitmap nodes and put +// the result in pds. +// Take account of looping edge if there was previously calculated. +void pass_mpi_collective::__is_post_dom_bitmap(function *fun, + basic_block bb, bitmap nodes, bitmap pds) +{ + edge e; + edge_iterator ei; + domination_status bb_dom_status; + domination_status cursor_dom_status; + + //printf("entered bb->index : %i\n",bb->index); + ((bb_data *) bb->aux)->mark1 = 1; + + if (bitmap_bit_p(nodes, bb->index)) + { + bitmap_set_bit(pds, bb->index); + ((bb_data *) bb->aux)->dom_status = DOMINATED; + return; + } + + if (EXIT_BLOCK_PTR_FOR_FN(fun) == bb) + { + ((bb_data *) bb->aux)->dom_status = NOT_DOMINATED; + return; + } + + // in case we are in a leaf it will return NOT_APPLICABLE + bb_dom_status = NOT_APPLICABLE; + + FOR_EACH_EDGE(e, ei, bb->succs) + { + if (((edge_data *) e->aux)->loop) + { + //printf("loop detected... Jumping out...\n"); + continue; //if marked as a loop or already visited, ignore + } + + if (! ((bb_data *) e->dest->aux)->mark1) + { + __is_post_dom_bitmap(fun, e->dest, nodes, pds); + } + + cursor_dom_status = ((bb_data *) e->dest->aux)->dom_status; + + if (cursor_dom_status == NOT_DOMINATED) + { + bb_dom_status = NOT_DOMINATED; + } + else if (cursor_dom_status == DOMINATED && bb_dom_status != NOT_DOMINATED) + { + bb_dom_status = DOMINATED; + } + } + + if (bb_dom_status == DOMINATED) + { + // add the bb to the pdset if it is post dominated by set + bitmap_set_bit(pds, bb->index); + } + + ((bb_data *) bb->aux)->dom_status = bb_dom_status; +} + +// wrapper of __is_post_dom_bitmap +void pass_mpi_collective::get_post_dom_bitmap(function *fun, + bitmap nodes, bitmap pds) +{ + __is_post_dom_bitmap(fun, ENTRY_BLOCK_PTR_FOR_FN(fun), + nodes, pds); + reset_bb_mark(fun); +} + +// calculate post dominantion frontier of a post dominated set of nodes +// in pds and put the result in pdf. +void pass_mpi_collective::get_post_dom_frontier(function *fun, + bitmap pds, bitmap pdf) +{ + //we check each bb, if a bb is in the postdom set, we check its + //most adjacents preds. If a pred is not in the postdom set, it + //is a elm of the frontier of set. + basic_block bb; + edge e; + edge_iterator ei; + + FOR_ALL_BB_FN(bb, fun) + { + if (bitmap_bit_p(pds, bb->index)) + { + //printf("entering %i\n", bb->index); + FOR_EACH_EDGE(e, ei, bb->preds) + { + //printf("\tchecking out my parent %i\n", e->src->index); + if (! ((edge_data *) e->aux)->loop + && !bitmap_bit_p(pds, e->src->index)) + { + bitmap_set_bit(pdf, e->src->index); + } + } + } + } +} + diff --git a/src/mpi_collective_graph_utils.cpp b/src/mpi_collective_graph_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b59f4d64956ebd72c7451b1a8e5d4ea638bd826b --- /dev/null +++ b/src/mpi_collective_graph_utils.cpp @@ -0,0 +1,224 @@ +#include <list> + +#include "mpi_collective.hpp" + +// bb aux alloc, free & reset +void pass_mpi_collective::alloc_bb_aux(function *fun) +{ + basic_block bb; + + FOR_ALL_BB_FN(bb, fun) + { + bb->aux = (bb_data *) new bb_data(); + bb_data *data = ((bb_data *) bb->aux); + data->mpi_code = LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; + bitmap_initialize(&data->dom, &bitmap_default_obstack); + bitmap_initialize(&data->post_dom, &bitmap_default_obstack); + bitmap_initialize(&data->dom_front, &bitmap_default_obstack); + bitmap_initialize(&data->post_dom_front, &bitmap_default_obstack); + for (int i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i) + { + data->collective_rank[i] = 0; + } + bitmap_initialize(&data->seens, &bitmap_default_obstack); + } + + reset_bb_mark(fun); +} + +void pass_mpi_collective::free_bb_aux(function *fun) +{ + basic_block bb; + FOR_ALL_BB_FN(bb, fun) + { + if (bb->aux != NULL) + { + bb_data *data = ((bb_data *) bb->aux); + bitmap_clear(&data->dom); + bitmap_clear(&data->post_dom); + bitmap_clear(&data->dom_front); + bitmap_clear(&data->post_dom_front); + bitmap_clear(&data->seens); + delete (bb_data *) bb->aux; + bb->aux = NULL; + } + } +} + +void pass_mpi_collective::reset_bb_mark(function *fun) +{ + basic_block bb; + + FOR_ALL_BB_FN(bb, fun) + { + ((bb_data *) bb->aux)->mark1 = 0; + ((bb_data *) bb->aux)->mark2 = 0; + } +} + +// edge aux alloc & free +void pass_mpi_collective::alloc_edge_aux(function *fun) +{ + basic_block bb; + edge e; + edge_iterator ei; + + FOR_ALL_BB_FN(bb, fun) + { + FOR_EACH_EDGE(e, ei, bb->succs) + { + e->aux = new edge_data(); + } + } +} + +void pass_mpi_collective::free_edge_aux(function *fun) +{ + basic_block bb; + edge e; + edge_iterator ei; + + FOR_ALL_BB_FN(bb, fun) + { + FOR_EACH_EDGE(e, ei, bb->succs) + { + if (e->aux != NULL) + { + delete (edge_data *) e->aux; + e->aux = NULL; + } + } + } +} + +// loop detection +// naive version of mark_edge (work but Omax(2^n)) +void pass_mpi_collective::__mark_edge_naif(function *fun) +{ + __mark_edge_naif(ENTRY_BLOCK_PTR_FOR_FN(fun)); +} + +void pass_mpi_collective::__mark_edge_naif(basic_block bb) +{ + edge e; + edge_iterator ei; + + ((bb_data *) bb->aux)->mark1 = 1; + FOR_EACH_EDGE(e, ei, bb->succs) + { + if (((bb_data *) e->dest->aux)->mark1) + { + ((edge_data *) e->aux)->loop = true; + } + else + { + __mark_edge_naif(e->dest); + } + } + ((bb_data *) bb->aux)->mark1 = 0; +} + +void pass_mpi_collective::__mark_edge_test(function *fun) +{ + + edge e1; + edge_iterator ei1; + std::list<basic_block> nodes1; + basic_block bb; + + edge e2; + edge_iterator ei2; + std::list<basic_block> nodes2; + basic_block cursor; + + int index; + + index = 0; + + nodes1.push_back(ENTRY_BLOCK_PTR_FOR_FN(fun)); + ((bb_data *) ENTRY_BLOCK_PTR_FOR_FN(fun)->aux)->mark1 = 1; + + while (!nodes1.empty()) + { + bb = nodes1.front(); + nodes1.pop_front(); + + FOR_EACH_EDGE(e1, ei1, bb->succs) + { + if (((bb_data *) e1->dest->aux)->mark1) + { + continue; + } + ((bb_data *) bb->aux)->mark1 = 1; + nodes1.push_back(e1->dest); + } + + if (EDGE_COUNT(bb->preds) < 2) + { + continue; + } + + ++index; + nodes2.clear(); + nodes2.push_back(bb); + ((bb_data *) bb->aux)->mark2 = index; + + while (!nodes2.empty()) + { + cursor = nodes2.front(); + nodes2.pop_front(); + + FOR_EACH_EDGE(e2, ei2, cursor->succs) + { + if (e2->dest == bb) + { + ((edge_data *) e2->aux)->loop = true; + } + if (((edge_data *) e2->aux)->loop) + { + continue; + } + + if (((bb_data *) e2->dest->aux)->mark2 >= index) + { + continue; + } + ((bb_data *) cursor->aux)->mark2 = index; + nodes2.push_back(e2->dest); + } + } + } + reset_bb_mark(fun); +} + +void pass_mpi_collective::mark_edge(function *fun) +{ + mark_edge(ENTRY_BLOCK_PTR_FOR_FN(fun)); + reset_bb_mark(fun); +} + +void pass_mpi_collective::mark_edge(basic_block bb) +{ + edge e; + edge_iterator ei; + + ((bb_data *) bb->aux)->mark1 = 1; + bitmap_set_bit(&((bb_data *) bb->aux)->seens, bb->index); + FOR_EACH_EDGE(e, ei, bb->succs) + { + if (((edge_data *) e->aux)->loop) + { + continue; + } + if (bitmap_bit_p(&((bb_data *) bb->aux)->seens, e->dest->index)) + { + ((edge_data *) e->aux)->loop = true; + } + if (! ((bb_data *) e->dest->aux)->mark1) + { + bitmap_ior_into(&((bb_data *) e->dest->aux)->seens, + &((bb_data *) bb->aux)->seens); + mark_edge(e->dest); + } + } +} diff --git a/src/mpi_collective_graphviz.cpp b/src/mpi_collective_graphviz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3eb238a68919721fec4d792a5ccb5449da86f798 --- /dev/null +++ b/src/mpi_collective_graphviz.cpp @@ -0,0 +1,135 @@ +#include <cstdio> +// basename +#include <filesystem> + +#include "mpi_collective.hpp" + +/* Build a filename (as a string) based on function name */ +char *pass_mpi_collective::cfgviz_generate_filename(function *fun, + const char *suffix) +{ + char *target_filename; + int line; + + target_filename = (char *)xmalloc(1024 * sizeof(char)); + line = LOCATION_LINE(fun->function_start_locus); + const char *mfilename = + std::filesystem::path(LOCATION_FILE(fun->function_start_locus)) + .filename().c_str(); + + snprintf(target_filename, 1024, "%s%s_%s_%d_%s.dot", + "dot/", + mfilename, + function_name(fun), + line, + suffix); + + return target_filename; +} + +/* Dump the graphviz representation of function 'fun' in file 'out' */ +void pass_mpi_collective::cfgviz_internal_dump(function *fun, FILE *out) +{ + basic_block bb; + edge_iterator eit; + edge e; + + bitmap_iterator bi; + unsigned int index; + + fprintf(out, "Digraph G{\n"); + FOR_ALL_BB_FN(bb, fun) + { + bb_data *data = ((bb_data *) bb->aux); + + fprintf(out, "%d [label=\"BB %d", bb->index, bb->index); + if (data->mpi_code != LAST_AND_UNUSED_MPI_COLLECTIVE_CODE) + { + fprintf(out, "|%s (%d) ", mpi_collective_name[data->mpi_code], + data->collective_rank[data->mpi_code]); + } + + if (! bitmap_empty_p(&data->dom)) + { + fprintf(out, "|dom("); + + EXECUTE_IF_SET_IN_BITMAP(&data->dom, 0, index, bi) + { + fprintf(out, "%d,", index); + } + fprintf(out, ")"); + } + + if (! bitmap_empty_p(&data->post_dom)) + { + fprintf(out, "|post_dom("); + EXECUTE_IF_SET_IN_BITMAP(&data->post_dom, 0, index, bi) + { + fprintf(out, "%d,", index); + } + fprintf(out, ")"); + } + + if (! bitmap_empty_p(&data->dom_front)) + { + fprintf(out, "|dom_front("); + EXECUTE_IF_SET_IN_BITMAP(&data->dom_front, 0, index, bi) + { + fprintf(out, "%d,", index); + } + fprintf(out, ")"); + } + + if (! bitmap_empty_p(&data->post_dom_front)) + { + fprintf(out, "|post_dom_front("); + EXECUTE_IF_SET_IN_BITMAP(&data->post_dom_front, 0, index, bi) + { + fprintf(out, "%d,", index); + } + fprintf(out, ")"); + } + + fprintf(out, "\" shape=ellipse]\n"); + + FOR_EACH_EDGE(e, eit, bb->succs) + { + const char *label = ""; + if (e->flags == EDGE_TRUE_VALUE) + { + label = "true"; + } + else if (e->flags == EDGE_FALSE_VALUE) + { + label = "false"; + } + + if (((edge_data *) e->aux)->loop) + { + label = "remove_loop"; + } + + fprintf(out, "%d -> %d [color=red label=\"%s\"]\n", + bb->index, e->dest->index, label); + } + } + fprintf(out, "}\n"); +} + +void pass_mpi_collective::cfgviz_dump(function *fun, const char *suffix) +{ + char *target_filename; + FILE *out; + + target_filename = cfgviz_generate_filename(fun, suffix); + + printf("[GRAPHVIZ] Generating CFG of function %s in file <%s>\n", + current_function_name(), target_filename); + + out = fopen(target_filename, "w"); + + cfgviz_internal_dump(fun, out); + + fclose(out); + free(target_filename); +} diff --git a/src/mpi_collective_pass.cpp b/src/mpi_collective_pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43b9420c26e7ddc9d24a47f20169bcb31a757c4a --- /dev/null +++ b/src/mpi_collective_pass.cpp @@ -0,0 +1,233 @@ +// 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; + } + } + } +} diff --git a/src/mpi_collective_warnings.cpp b/src/mpi_collective_warnings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75c1183bd2b4c2a89c82741ac0722addb8fd62cb --- /dev/null +++ b/src/mpi_collective_warnings.cpp @@ -0,0 +1,185 @@ +// std::max +#include <algorithm> + +#include "mpi_collective.hpp" + +void pass_mpi_collective::rank_collective(function *fun) +{ + __rank_collective(EXIT_BLOCK_PTR_FOR_FN(fun)); + reset_bb_mark(fun); +} + +void pass_mpi_collective::__rank_collective(basic_block bb) +{ + edge e; + edge_iterator ei; + + ((bb_data *) bb->aux)->mark1 = 1; + FOR_EACH_EDGE(e, ei, bb->preds) + { + if (((edge_data *) e->aux)->loop) + { + continue; + } + + if (! ((bb_data *) e->src->aux)->mark1) + { + __rank_collective(e->src); + } + + for (int mpi_code = 0; + mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; + ++mpi_code) + { + ((bb_data *) bb->aux)->collective_rank[mpi_code] = + std::max(((bb_data *) bb->aux)->collective_rank[mpi_code], + ((bb_data *) e->src->aux)->collective_rank[mpi_code]); + if (((bb_data *) bb->aux)->mpi_code == mpi_code) + { + ((bb_data *) bb->aux)->collective_rank[mpi_code]++; + collective_max_rank[mpi_code] = + std::max(collective_max_rank[mpi_code], + ((bb_data *) bb->aux)->collective_rank[mpi_code]); + //printf("collective max rank for %i up to %i\n", + // mpi_code, collective_max_rank[mpi_code]); + } + } + } +} + +void pass_mpi_collective::better_rank_collective(function *fun) +{ + size_t i; + int next_rank = 0; + + for (i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i) + { + next_rank = __better_rank_collective(EXIT_BLOCK_PTR_FOR_FN(fun), + (enum mpi_collective_code) i, + next_rank); + } + reset_bb_mark(fun); +} + +int pass_mpi_collective::__better_rank_collective(basic_block bb, + mpi_collective_code mpi_code, int rank) +{ + edge e; + edge_iterator ei; + int next_rank; + + next_rank = rank; + ((bb_data *) bb->aux)->mark1 = mpi_code + 1; + + FOR_EACH_EDGE(e, ei, bb->preds) + { + if (((edge_data *) e->aux)->loop) + { + continue; + } + + // cache or travell + if (((bb_data *) e->src->aux)->mark1 <= mpi_code) + { + next_rank = + std::max(next_rank, + __better_rank_collective(e->src, mpi_code, rank)); + } + else + { + next_rank = + std::max(next_rank, + ((bb_data *) e->src->aux)->collective_rank[mpi_code]); + } + } + // set mpi code + if (((bb_data *) bb->aux)->mpi_code == mpi_code) + { + next_rank++; + } + ((bb_data *) bb->aux)->collective_rank[mpi_code] = next_rank; + return next_rank; +} + +void pass_mpi_collective::get_mpi_coll_rank(function *fun, + int rank, int mpi_code, bitmap mpi_coll) +{ + basic_block bb; + + FOR_ALL_BB_FN(bb, fun) + { + if (((bb_data *) bb->aux)->mpi_code == mpi_code + && ((bb_data *) bb->aux)->collective_rank[mpi_code] == rank) + { + //printf("bb %i is coll %i of rank %i\n", + // bb->index, mpi_code, rank); + bitmap_set_bit(mpi_coll, bb->index); + } + } +} + +void pass_mpi_collective::raise_warning_if_mpi_wrong(function *fun) +{ + for (int mpi_code = 0; mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; + ++mpi_code) + { + bitmap_head pds_head; + bitmap_head pdf_head; + bitmap_head nodes_head; + + bitmap pds = &pds_head; + bitmap pdf = &pdf_head; + bitmap nodes = &nodes_head; + bitmap tmp = NULL; + + bitmap_initialize(pds, &bitmap_default_obstack); + bitmap_initialize(pdf, &bitmap_default_obstack); + bitmap_initialize(nodes, &bitmap_default_obstack); + int stop = 0; + + for (int i = 1 ; i < collective_max_rank[mpi_code] + 1 ; i++) + { + printf("mpi_code: %i at rank: %i\n", mpi_code, i); + // DONE: split in 2, get mpi set & find set post dom + get_mpi_coll_rank(fun, i, mpi_code, nodes); + get_post_dom_bitmap(fun, nodes, pds); + get_post_dom_frontier(fun, pds, pdf); + + printf("----\n"); + debug_bitmap(nodes); + debug_bitmap(pds); + debug_bitmap(pdf); + + while (! bitmap_empty_p(pdf)) + { + stop++; + if (stop > 10) + { return; } + + printf("WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + // print warning here + + bitmap_clear(nodes); + bitmap_clear(pds); + + // swap nodes & pdf + { + tmp = nodes; + nodes = pdf; + pdf = tmp; + } + get_post_dom_bitmap(fun, nodes, pds); + get_post_dom_frontier(fun, pds, pdf); + + printf("----\n"); + debug_bitmap(nodes); + debug_bitmap(pds); + debug_bitmap(pdf); + } + bitmap_clear(nodes); + bitmap_clear(pds); + bitmap_clear(pdf); + } + } +} + diff --git a/src/pass_mpi_collective.cpp b/src/pass_mpi_collective.cpp deleted file mode 100644 index 74baed20a5b5f719bb66a04226424774c76497f1..0000000000000000000000000000000000000000 --- a/src/pass_mpi_collective.cpp +++ /dev/null @@ -1,973 +0,0 @@ -// 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> -//bitmaps -#include <bitmap.h> -// basename -#include <filesystem> -// list -#include <list> - -// our pass -#include "pass_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); - label_collec(fun); - label_dom(fun); - label_dom_front(fun); - - alloc_edge_aux(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; -} - -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))); - } - } - } - } - } -} - -// 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); -} - -// 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 - } - } - } -} - -void pass_mpi_collective::alloc_bb_aux(function *fun) -{ - basic_block bb; - - FOR_ALL_BB_FN(bb, fun) - { - bb->aux = (bb_data *) new bb_data(); - bb_data *data = ((bb_data *) bb->aux); - data->mpi_code = LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; - bitmap_initialize(&data->dom, &bitmap_default_obstack); - bitmap_initialize(&data->post_dom, &bitmap_default_obstack); - bitmap_initialize(&data->dom_front, &bitmap_default_obstack); - bitmap_initialize(&data->post_dom_front, &bitmap_default_obstack); - for (int i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i) - { - data->collective_rank[i] = 0; - } - bitmap_initialize(&data->seens, &bitmap_default_obstack); - } - - reset_bb_mark(fun); -} - -// gestions des aux -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; - } - } - } -} - -void pass_mpi_collective::free_bb_aux(function *fun) -{ - basic_block bb; - FOR_ALL_BB_FN(bb, fun) - { - if (bb->aux != NULL) - { - bb_data *data = ((bb_data *) bb->aux); - bitmap_clear(&data->dom); - bitmap_clear(&data->post_dom); - bitmap_clear(&data->dom_front); - bitmap_clear(&data->post_dom_front); - bitmap_clear(&data->seens); - delete (bb_data *) bb->aux; - bb->aux = NULL; - } - } -} - -// calculate dominance -void pass_mpi_collective::label_dom(function *fun) -{ - basic_block bb; - auto_vec<basic_block> dom_gccvec; - auto_vec<basic_block> post_dom_gccvec; - size_t size_dom; - size_t size_post_dom; - - calculate_dominance_info(CDI_DOMINATORS); - calculate_dominance_info(CDI_POST_DOMINATORS); - - FOR_ALL_BB_FN(bb, fun) - { - bb_data *data = ((bb_data *) bb->aux); - - dom_gccvec = get_all_dominated_blocks(CDI_DOMINATORS, bb); - size_dom = dom_gccvec.length(); - for (size_t i = 0; i < size_dom; ++i) - { - if (dom_gccvec[i]->index != bb->index) - { - bitmap_set_bit(&data->dom, dom_gccvec[i]->index); - } - } - - post_dom_gccvec = get_all_dominated_blocks(CDI_POST_DOMINATORS, bb); - size_post_dom = post_dom_gccvec.length(); - for (size_t i = 0; i < size_post_dom; ++i) - { - if (post_dom_gccvec[i]->index != bb->index) - { - bitmap_set_bit(&data->post_dom, post_dom_gccvec[i]->index); - } - } - } -} - -void pass_mpi_collective::label_dom_front(function *fun) -{ - edge p; - edge_iterator ei; - basic_block bb; - basic_block dom_bb; - basic_block runner; - bb_data *data; - - FOR_EACH_BB_FN(bb, fun) - { - if (EDGE_COUNT(bb->preds) < 2) - { - continue; - } - dom_bb = get_immediate_dominator(CDI_DOMINATORS, bb); - FOR_EACH_EDGE(p, ei, bb->preds) - { - runner = p->src; - if (runner == ENTRY_BLOCK_PTR_FOR_FN(fun)) - { - continue; - } - while (runner != dom_bb) - { - data = (bb_data *) runner->aux; - if (bitmap_bit_p(&data->dom_front, bb->index)) - { - break; - } - bitmap_set_bit(&data->dom_front, bb->index); - runner = get_immediate_dominator(CDI_DOMINATORS, runner); - } - } - } - - FOR_EACH_BB_FN(bb, fun) - { - if (EDGE_COUNT(bb->succs) < 2) - { - continue; - } - dom_bb = get_immediate_dominator(CDI_POST_DOMINATORS, bb); - FOR_EACH_EDGE(p, ei, bb->succs) - { - runner = p->dest; - if (runner == EXIT_BLOCK_PTR_FOR_FN(fun)) - { - continue; - } - while (runner != dom_bb) - { - data = (bb_data *) runner->aux; - if (bitmap_bit_p(&data->post_dom_front, bb->index)) - { - break; - } - bitmap_set_bit(&data->post_dom_front, bb->index); - runner = get_immediate_dominator(CDI_POST_DOMINATORS, runner); - } - } - } -} - -void pass_mpi_collective::free_dom_data() -{ - free_dominance_info(CDI_DOMINATORS); - free_dominance_info(CDI_POST_DOMINATORS); -} - -// parkour de graph -void pass_mpi_collective::reset_bb_mark(function *fun) -{ - basic_block bb; - - FOR_ALL_BB_FN(bb, fun) - { - ((bb_data *) bb->aux)->mark1 = 0; - ((bb_data *) bb->aux)->mark2 = 0; - } -} - -void pass_mpi_collective::alloc_edge_aux(function *fun) -{ - basic_block bb; - edge e; - edge_iterator ei; - - FOR_ALL_BB_FN(bb, fun) - { - FOR_EACH_EDGE(e, ei, bb->succs) - { - e->aux = new edge_data(); - } - } -} - -void pass_mpi_collective::free_edge_aux(function *fun) -{ - basic_block bb; - edge e; - edge_iterator ei; - - FOR_ALL_BB_FN(bb, fun) - { - FOR_EACH_EDGE(e, ei, bb->succs) - { - if (e->aux != NULL) - { - delete (edge_data *) e->aux; - e->aux = NULL; - } - } - } -} - -// naive version of mark_edge (work but Omax(2^n)) -void pass_mpi_collective::__mark_edge_naif(function *fun) -{ - __mark_edge_naif(ENTRY_BLOCK_PTR_FOR_FN(fun)); -} - -void pass_mpi_collective::__mark_edge_naif(basic_block bb) -{ - edge e; - edge_iterator ei; - - ((bb_data *) bb->aux)->mark1 = 1; - FOR_EACH_EDGE(e, ei, bb->succs) - { - if (((bb_data *) e->dest->aux)->mark1) - { - ((edge_data *) e->aux)->loop = true; - } - else - { - __mark_edge_naif(e->dest); - } - } - ((bb_data *) bb->aux)->mark1 = 0; -} - -void pass_mpi_collective::__mark_edge(function *fun) -{ - - edge e1; - edge_iterator ei1; - std::list<basic_block> nodes1; - basic_block bb; - - edge e2; - edge_iterator ei2; - std::list<basic_block> nodes2; - basic_block cursor; - - int index; - - index = 0; - - nodes1.push_back(ENTRY_BLOCK_PTR_FOR_FN(fun)); - ((bb_data *) ENTRY_BLOCK_PTR_FOR_FN(fun)->aux)->mark1 = 1; - - while (!nodes1.empty()) - { - bb = nodes1.front(); - nodes1.pop_front(); - - FOR_EACH_EDGE(e1, ei1, bb->succs) - { - if (((bb_data *) e1->dest->aux)->mark1) - { - continue; - } - ((bb_data *) bb->aux)->mark1 = 1; - nodes1.push_back(e1->dest); - } - - if (EDGE_COUNT(bb->preds) < 2) - { - continue; - } - - ++index; - nodes2.clear(); - nodes2.push_back(bb); - ((bb_data *) bb->aux)->mark2 = index; - - while (!nodes2.empty()) - { - cursor = nodes2.front(); - nodes2.pop_front(); - - FOR_EACH_EDGE(e2, ei2, cursor->succs) - { - if (e2->dest == bb) - { - ((edge_data *) e2->aux)->loop = true; - } - if (((edge_data *) e2->aux)->loop) - { - continue; - } - - if (((bb_data *) e2->dest->aux)->mark2 >= index) - { - continue; - } - ((bb_data *) cursor->aux)->mark2 = index; - nodes2.push_back(e2->dest); - } - } - } - reset_bb_mark(fun); -} - -void pass_mpi_collective::mark_edge(function *fun) -{ - mark_edge(ENTRY_BLOCK_PTR_FOR_FN(fun)); - reset_bb_mark(fun); -} - -void pass_mpi_collective::mark_edge(basic_block bb) -{ - edge e; - edge_iterator ei; - - ((bb_data *) bb->aux)->mark1 = 1; - bitmap_set_bit(&((bb_data *) bb->aux)->seens, bb->index); - FOR_EACH_EDGE(e, ei, bb->succs) - { - if (((edge_data *) e->aux)->loop) - { - continue; - } - if (bitmap_bit_p(&((bb_data *) bb->aux)->seens, e->dest->index)) - { - ((edge_data *) e->aux)->loop = true; - } - if (! ((bb_data *) e->dest->aux)->mark1) - { - bitmap_ior_into(&((bb_data *) e->dest->aux)->seens, - &((bb_data *) bb->aux)->seens); - mark_edge(e->dest); - } - } -} - -void pass_mpi_collective::rank_collective(function *fun) -{ - __rank_collective(EXIT_BLOCK_PTR_FOR_FN(fun)); - reset_bb_mark(fun); -} - -void pass_mpi_collective::__rank_collective(basic_block bb) -{ - edge e; - edge_iterator ei; - - ((bb_data *) bb->aux)->mark1 = 1; - FOR_EACH_EDGE(e, ei, bb->preds) - { - if (((edge_data *) e->aux)->loop) - { - continue; - } - - if (! ((bb_data *) e->src->aux)->mark1) - { - __rank_collective(e->src); - } - - for (int mpi_code = 0; - mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; - ++mpi_code) - { - ((bb_data *) bb->aux)->collective_rank[mpi_code] = - std::max(((bb_data *) bb->aux)->collective_rank[mpi_code], - ((bb_data *) e->src->aux)->collective_rank[mpi_code]); - if (((bb_data *) bb->aux)->mpi_code == mpi_code) - { - ((bb_data *) bb->aux)->collective_rank[mpi_code]++; - collective_max_rank[mpi_code] = - std::max(collective_max_rank[mpi_code], - ((bb_data *) bb->aux)->collective_rank[mpi_code]); - //printf("collective max rank for %i up to %i\n", - // mpi_code, collective_max_rank[mpi_code]); - } - } - } -} - -void pass_mpi_collective::better_rank_collective(function *fun) -{ - size_t i; - int next_rank = 0; - - for (i = 0; i < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++i) - { - next_rank = __better_rank_collective(EXIT_BLOCK_PTR_FOR_FN(fun), - (enum mpi_collective_code) i, - next_rank); - } - reset_bb_mark(fun); -} - -int pass_mpi_collective::__better_rank_collective(basic_block bb, - mpi_collective_code mpi_code, int rank) -{ - edge e; - edge_iterator ei; - int next_rank; - - next_rank = rank; - ((bb_data *) bb->aux)->mark1 = mpi_code + 1; - - FOR_EACH_EDGE(e, ei, bb->preds) - { - if (((edge_data *) e->aux)->loop) - { - continue; - } - - // cache or travell - if (((bb_data *) e->src->aux)->mark1 <= mpi_code) - { - next_rank = - std::max(next_rank, - __better_rank_collective(e->src, mpi_code, rank)); - } - else - { - next_rank = - std::max(next_rank, - ((bb_data *) e->src->aux)->collective_rank[mpi_code]); - } - } - // set mpi code - if (((bb_data *) bb->aux)->mpi_code == mpi_code) - { - next_rank++; - } - ((bb_data *) bb->aux)->collective_rank[mpi_code] = next_rank; - return next_rank; -} - -void pass_mpi_collective::get_mpi_coll_rank(function *fun, - int rank, int mpi_code, bitmap mpi_coll) -{ - basic_block bb; - - FOR_ALL_BB_FN(bb, fun) - { - if (((bb_data *) bb->aux)->mpi_code == mpi_code - && ((bb_data *) bb->aux)->collective_rank[mpi_code] == rank) - { - //printf("bb %i is coll %i of rank %i\n", - // bb->index, mpi_code, rank); - bitmap_set_bit(mpi_coll, bb->index); - } - } -} - -void pass_mpi_collective::__is_post_dom_bitmap(function *fun, - basic_block bb, bitmap nodes, bitmap pds) -{ - edge e; - edge_iterator ei; - domination_status bb_dom_status; - domination_status cursor_dom_status; - - //printf("entered bb->index : %i\n",bb->index); - ((bb_data *) bb->aux)->mark1 = 1; - - if (bitmap_bit_p(nodes, bb->index)) - { - bitmap_set_bit(pds, bb->index); - ((bb_data *) bb->aux)->dom_status = DOMINATED; - return; - } - - if (EXIT_BLOCK_PTR_FOR_FN(fun) == bb) - { - ((bb_data *) bb->aux)->dom_status = NOT_DOMINATED; - return; - } - - // in case we are in a leaf it will return NOT_APPLICABLE - bb_dom_status = NOT_APPLICABLE; - - FOR_EACH_EDGE(e, ei, bb->succs) - { - if (((edge_data *) e->aux)->loop) - { - //printf("loop detected... Jumping out...\n"); - continue; //if marked as a loop or already visited, ignore - } - - if (! ((bb_data *) e->dest->aux)->mark1) - { - __is_post_dom_bitmap(fun, e->dest, nodes, pds); - } - - cursor_dom_status = ((bb_data *) e->dest->aux)->dom_status; - - if (cursor_dom_status == NOT_DOMINATED) - { - bb_dom_status = NOT_DOMINATED; - } - else if (cursor_dom_status == DOMINATED && bb_dom_status != NOT_DOMINATED) - { - bb_dom_status = DOMINATED; - } - } - - if (bb_dom_status == DOMINATED) - { - // add the bb to the pdset if it is post dominated by set - bitmap_set_bit(pds, bb->index); - } - - ((bb_data *) bb->aux)->dom_status = bb_dom_status; -} - -void pass_mpi_collective::get_post_dom_bitmap(function *fun, - bitmap nodes, bitmap pds) -{ - __is_post_dom_bitmap(fun, ENTRY_BLOCK_PTR_FOR_FN(fun), - nodes, pds); - reset_bb_mark(fun); -} - -void pass_mpi_collective::get_post_dom_frontier(function *fun, - bitmap pds, bitmap pdf) -{ - //we check each bb, if a bb is in the postdom set, we check its - //most adjacents preds. If a pred is not in the postdom set, it - //is a elm of the frontier of set. - basic_block bb; - edge e; - edge_iterator ei; - - FOR_ALL_BB_FN(bb, fun) - { - if (bitmap_bit_p(pds, bb->index)) - { - //printf("entering %i\n", bb->index); - FOR_EACH_EDGE(e, ei, bb->preds) - { - //printf("\tchecking out my parent %i\n", e->src->index); - if (! ((edge_data *) e->aux)->loop - && !bitmap_bit_p(pds, e->src->index)) - { - bitmap_set_bit(pdf, e->src->index); - } - } - } - } -} - -void pass_mpi_collective::raise_warning_if_mpi_wrong(function *fun) -{ - for (int mpi_code = 0; mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; - ++mpi_code) - { - bitmap_head pds_head; - bitmap_head pdf_head; - bitmap_head nodes_head; - - bitmap pds = &pds_head; - bitmap pdf = &pdf_head; - bitmap nodes = &nodes_head; - bitmap tmp = NULL; - - bitmap_initialize(pds, &bitmap_default_obstack); - bitmap_initialize(pdf, &bitmap_default_obstack); - bitmap_initialize(nodes, &bitmap_default_obstack); - int stop = 0; - - for (int i = 1 ; i < collective_max_rank[mpi_code] + 1 ; i++) - { - printf("mpi_code: %i at rank: %i\n", mpi_code, i); - // DONE: split in 2, get mpi set & find set post dom - get_mpi_coll_rank(fun, i, mpi_code, nodes); - get_post_dom_bitmap(fun, nodes, pds); - get_post_dom_frontier(fun, pds, pdf); - - printf("----\n"); - debug_bitmap(nodes); - debug_bitmap(pds); - debug_bitmap(pdf); - - while (! bitmap_empty_p(pdf)) - { - stop++; - if (stop > 10) - { return; } - - printf("WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!"); - // print warning here - - bitmap_clear(nodes); - bitmap_clear(pds); - - // swap nodes & pdf - { - tmp = nodes; - nodes = pdf; - pdf = tmp; - } - get_post_dom_bitmap(fun, nodes, pds); - get_post_dom_frontier(fun, pds, pdf); - - printf("----\n"); - debug_bitmap(nodes); - debug_bitmap(pds); - debug_bitmap(pdf); - } - bitmap_clear(nodes); - bitmap_clear(pds); - bitmap_clear(pdf); - } - } -} - -//============================ GRAPHVIZ ===================================== - -/* Build a filename (as a string) based on function name */ -char *pass_mpi_collective::cfgviz_generate_filename(function *fun, - const char *suffix) -{ - char *target_filename; - int line; - - target_filename = (char *)xmalloc(1024 * sizeof(char)); - line = LOCATION_LINE(fun->function_start_locus); - const char *mfilename = - std::filesystem::path(LOCATION_FILE(fun->function_start_locus)) - .filename().c_str(); - - snprintf(target_filename, 1024, "%s%s_%s_%d_%s.dot", - "dot/", - mfilename, - function_name(fun), - line, - suffix); - - return target_filename; -} - -/* Dump the graphviz representation of function 'fun' in file 'out' */ -void pass_mpi_collective::cfgviz_internal_dump(function *fun, FILE *out) -{ - basic_block bb; - edge_iterator eit; - edge e; - - bitmap_iterator bi; - unsigned int index; - - fprintf(out, "Digraph G{\n"); - FOR_ALL_BB_FN(bb, fun) - { - bb_data *data = ((bb_data *) bb->aux); - - fprintf(out, "%d [label=\"BB %d", bb->index, bb->index); - if (data->mpi_code != LAST_AND_UNUSED_MPI_COLLECTIVE_CODE) - { - fprintf(out, "|%s (%d) ", mpi_collective_name[data->mpi_code], - data->collective_rank[data->mpi_code]); - } - - if (! bitmap_empty_p(&data->dom)) - { - fprintf(out, "|dom("); - - EXECUTE_IF_SET_IN_BITMAP(&data->dom, 0, index, bi) - { - fprintf(out, "%d,", index); - } - fprintf(out, ")"); - } - - if (! bitmap_empty_p(&data->post_dom)) - { - fprintf(out, "|post_dom("); - EXECUTE_IF_SET_IN_BITMAP(&data->post_dom, 0, index, bi) - { - fprintf(out, "%d,", index); - } - fprintf(out, ")"); - } - - if (! bitmap_empty_p(&data->dom_front)) - { - fprintf(out, "|dom_front("); - EXECUTE_IF_SET_IN_BITMAP(&data->dom_front, 0, index, bi) - { - fprintf(out, "%d,", index); - } - fprintf(out, ")"); - } - - if (! bitmap_empty_p(&data->post_dom_front)) - { - fprintf(out, "|post_dom_front("); - EXECUTE_IF_SET_IN_BITMAP(&data->post_dom_front, 0, index, bi) - { - fprintf(out, "%d,", index); - } - fprintf(out, ")"); - } - - fprintf(out, "\" shape=ellipse]\n"); - - FOR_EACH_EDGE(e, eit, bb->succs) - { - const char *label = ""; - if (e->flags == EDGE_TRUE_VALUE) - { - label = "true"; - } - else if (e->flags == EDGE_FALSE_VALUE) - { - label = "false"; - } - - if (((edge_data *) e->aux)->loop) - { - label = "remove_loop"; - } - - fprintf(out, "%d -> %d [color=red label=\"%s\"]\n", - bb->index, e->dest->index, label); - } - } - fprintf(out, "}\n"); -} - -void pass_mpi_collective::cfgviz_dump(function *fun, const char *suffix) -{ - char *target_filename; - FILE *out; - - target_filename = cfgviz_generate_filename(fun, suffix); - - printf("[GRAPHVIZ] Generating CFG of function %s in file <%s>\n", - current_function_name(), target_filename); - - out = fopen(target_filename, "w"); - - cfgviz_internal_dump(fun, out); - - fclose(out); - free(target_filename); -} diff --git a/src/plugin.cpp b/src/plugin.cpp index 7c3a517fc8b7a1ac7123d585e3e12a97b3c79c9a..3ee2fbb41aaa94503e5e62e12ea50ec9203949c4 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -8,7 +8,7 @@ #include <context.h> // our pass -#include "pass_mpi_collective.hpp" +#include "mpi_collective.hpp" /* Global variable required for plugin to execute */ int plugin_is_GPL_compatible;