diff --git a/Makefile b/Makefile index 41faad1dee945ca30eb82d285228a7014eab4fb3..a0bb687d41ef38b337d6f5f973284fd9c9616860 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC=mpicc CXX=mpicxx FLAGS=-Wall -Wextra -Werror -fPIC -fno-rtti -TEST_FLAGS=-Wall -Wextra -Werror -fPIC +TEST_FLAGS=-Wall -Wextra -fPIC #-Werror LDFLAGS=-shared INCLUDE=-I ./include diff --git a/include/mpi_collective.hpp b/include/mpi_collective.hpp index 2f4392f8f038e9023237426dda7658065d4f0596..3fb159dfc207fb0331a2a2cc2c3a68da44541e0c 100644 --- a/include/mpi_collective.hpp +++ b/include/mpi_collective.hpp @@ -1,7 +1,7 @@ #ifndef __MPI_COLLECTIVE_HPP_ #define __MPI_COLLECTIVE_HPP_ -// dependance de tree-pass.H +// dependance of tree-pass.H #include <gcc-plugin.h> // declare opt_pass #include <tree-pass.h> @@ -125,6 +125,10 @@ public: // with the same rank in a bitmap void get_mpi_coll_rank( function *fun, int rank, int mpi_code, bitmap mpi_coll); + //get gimple expr for warning format and location + gimple* get_first_stmt(basic_block bb); + gimple* get_mpi_stmt(basic_block bb); + gimple* get_first_non_mpi_stmt(basic_block bb); // raise warnings when mpi collective are badly uses void raise_warning_mpi_rank(function *fun); void raise_warning_mpi_order(function *fun); diff --git a/src/mpi_collective_dominance.cpp b/src/mpi_collective_dominance.cpp index 87369883d0f7dff21f8af56a8911066523c3cbb1..09a83bfe9107c5c0a6a11868cc829047af5b9733 100644 --- a/src/mpi_collective_dominance.cpp +++ b/src/mpi_collective_dominance.cpp @@ -142,7 +142,7 @@ void pass_mpi_collective::label_post_dom_front(function *fun) // 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. +// Take account of looping edge if it was previously calculated. void pass_mpi_collective::__is_post_dom_bitmap(function *fun, basic_block bb, bitmap nodes, bitmap pds) { @@ -152,7 +152,7 @@ void pass_mpi_collective::__is_post_dom_bitmap(function *fun, domination_status cursor_dom_status; //printf("entered bb->index : %i\n",bb->index); - ((bb_data *) bb->aux)->mark1 = 1; + ((bb_data *) bb->aux)->mark1 = 1; //node has been visited if (bitmap_bit_p(nodes, bb->index)) { diff --git a/src/mpi_collective_pragma.cpp b/src/mpi_collective_pragma.cpp index be5dde3ebf6dc2cd691a17cac7230c05d9abe487..feb1f65e0dcb40f39ad673d7492eb14e6bb36b44 100644 --- a/src/mpi_collective_pragma.cpp +++ b/src/mpi_collective_pragma.cpp @@ -7,6 +7,9 @@ // IDENTIFIER_POINTER #include <tree.h> +//gcc error +#include <diagnostic.h> + #include "mpi_collective.hpp" void register_mpicoll_check_pragma(void *event_data, void *data) @@ -26,7 +29,9 @@ void mpicoll_check_pragma(cpp_reader *) // on a pas acces a la fonction courante sans passer par cfun if (cfun) { - printf("#pragma ProjectCA mpicoll_check is not allowed inside functions"); + error_at (cfun->function_start_locus + , "pragma ProjectCA %s is not allowed inside functions" + , "mpicoll_check"); return; } diff --git a/src/mpi_collective_warnings.cpp b/src/mpi_collective_warnings.cpp index ec392e78fccbf33cc4d510b345f58b62862a4d71..ea89de75b9fc895a015b9ff6960d814a23054473 100644 --- a/src/mpi_collective_warnings.cpp +++ b/src/mpi_collective_warnings.cpp @@ -1,42 +1,65 @@ // std::max #include <algorithm> +#include <stack> #include "mpi_collective.hpp" +// dependance of context.h +#include <gcc-plugin.h> +// 'g' global variable +#include <context.h> +// dependence of gimple.h +#include <tree.h> +//gimple iterator dependence +#include <gimple.h> +// gsi +#include <gimple-iterator.h> +//error formating gcc-like +#include <diagnostic.h> + + +//wrapper function void pass_mpi_collective::rank_collective(function *fun) { + //we calculate collective rank starting from the bottom __rank_collective(EXIT_BLOCK_PTR_FOR_FN(fun)); reset_bb_mark(fun); } +//recursive function calculating the rank for each mpi collective. void pass_mpi_collective::__rank_collective(basic_block bb) { edge e; edge_iterator ei; - ((bb_data *) bb->aux)->mark1 = 1; + ((bb_data *) bb->aux)->mark1 = 1; //we visited this node FOR_EACH_EDGE(e, ei, bb->preds) { - if (((edge_data *) e->aux)->loop) + if (((edge_data *) e->aux)->loop)//loop in the graph ; do not compute { continue; } - if (! ((bb_data *) e->src->aux)->mark1) + if (! ((bb_data *) e->src->aux)->mark1) //unvisited node { - __rank_collective(e->src); + __rank_collective(e->src); //recursion on parent nodes } - + + //(note that entering this for loop imply we already processed our + //parent node) for (int mpi_code = 0; mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; - ++mpi_code) + ++mpi_code) //the rank is per collective, thus we test on each mpicode. { ((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) { + //if we are a new collective of this mpi_code, then we are in a new + //rank ; we increment to reflect that. ((bb_data *) bb->aux)->collective_rank[mpi_code]++; + //then we update the global max to be sure collective_max_rank[mpi_code] = std::max(collective_max_rank[mpi_code], ((bb_data *) bb->aux)->collective_rank[mpi_code]); @@ -47,6 +70,7 @@ void pass_mpi_collective::__rank_collective(basic_block bb) } } +//set in a bitmap the index of a bb that have the same rank for a collective void pass_mpi_collective::get_mpi_coll_rank(function *fun, int rank, int mpi_code, bitmap mpi_coll) { @@ -64,12 +88,58 @@ void pass_mpi_collective::get_mpi_coll_rank(function *fun, } } +//get first gimple statement in bb +gimple * pass_mpi_collective::get_first_stmt(basic_block bb) +{ + return bb->il.gimple.seq; +} + +//get gimple statement in bb that is its mpi call +//This obv only works with bb that have a mpi call inside it. +gimple * pass_mpi_collective::get_mpi_stmt(basic_block bb) +{ + gimple_stmt_iterator gsi; + gimple *stmt; + + for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) + { + stmt = gsi_stmt(gsi); + if(is_mpi_collec(stmt) == ((bb_data *) bb->aux)->mpi_code) + { + return stmt; + } + } + //should not happen + printf("ARGSH"); + return NULL; +} + +//get gimple statement in bb that is its mpi call +//This obv only works with bb that have a mpi call inside it. +gimple * pass_mpi_collective::get_first_non_mpi_stmt(basic_block bb) +{ + gimple_stmt_iterator gsi; + gimple *stmt; + + for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) + { + stmt = gsi_stmt(gsi); + if(!is_mpi_func(stmt)) + { + return stmt; + } + } + //should not happen + printf("ARGSH"); + return NULL; +} + void pass_mpi_collective::raise_warning_mpi_rank(function *fun) { int mpi_code; - bitmap_head pds_head; - bitmap_head pdf_head; + bitmap_head pds_head; //postdominance set (pds) + bitmap_head pdf_head; //postdominance frontier (pdf) bitmap_head nodes_head; bitmap pds = &pds_head; @@ -87,7 +157,12 @@ void pass_mpi_collective::raise_warning_mpi_rank(function *fun) for (mpi_code = 0; mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++mpi_code) { - + //for a given set of nodes of of same mpi collective and rank, + //we calculate its post-dominance frontier. + //A Warning occurs when its postdominance frontier is not empty : + //indeed, this mean that some path in our cfg does not necessarily go + //through this collective, which means, some of our MPI threads does not + //go through the same mpi collective at the same moment => deadlocks for (int rank = 1 ; rank < collective_max_rank[mpi_code] + 1 ; rank++) { //printf("mpi_code: %i at rank: %i\n", mpi_code, i); @@ -101,23 +176,29 @@ void pass_mpi_collective::raise_warning_mpi_rank(function *fun) //debug_bitmap(pds); //debug_bitmap(pdf); + std::stack<int> bb_pdf_indx_stack; //indexes of bb forming the pdf + std::stack<int> bb_call_indx_stack; ///indexes of bb doing the mpi call if (! bitmap_empty_p(pdf)) { - // TODO make better warning messages - printf("Mpi Collective %s incomplete rank at bbs: ", - mpi_collective_name[mpi_code]); + //printf("MPI Collective %s incomplete rank at bbs: ", + // mpi_collective_name[mpi_code]); + + //we add every call to this mpi collective in our stack. EXECUTE_IF_SET_IN_BITMAP(nodes, 0, index, bi) - { - printf("%i, ", index); + { + bb_call_indx_stack.push(index); + //printf("%i, ", index); } - printf("\n"); } + while (! bitmap_empty_p(pdf)) { + //we stack the iterative pdf into an other stack. EXECUTE_IF_SET_IN_BITMAP(pdf, 0, index, bi) { - printf("Divergence from bb %i\n", index); + bb_pdf_indx_stack.push(index); + //printf("Divergence from bb %i\n", index); } bitmap_clear(nodes); @@ -140,6 +221,37 @@ void pass_mpi_collective::raise_warning_mpi_rank(function *fun) bitmap_clear(nodes); bitmap_clear(pds); bitmap_clear(pdf); + + //write the error message if needed by processing the stack + if (!bb_pdf_indx_stack.empty()) + { + location_t loc; + //first divergence possible + loc = gimple_location( + get_first_non_mpi_stmt(get_bb_from_index(fun, bb_pdf_indx_stack.top()))); + warning_at (loc + , 0 + , "The MPI Collective %s(%i) might be unmatched in some MPI processes, diverging from here:" + , mpi_collective_name[mpi_code], rank); + bb_pdf_indx_stack.pop(); + + while(!bb_call_indx_stack.empty()) + { + loc = gimple_location( + get_mpi_stmt(get_bb_from_index(fun, bb_call_indx_stack.top()))); + inform (loc, "MPI collective %s(%i) called here." + , mpi_collective_name[mpi_code], rank); + bb_call_indx_stack.pop(); + } + + while(!bb_pdf_indx_stack.empty()) + { + loc = gimple_location( + get_first_non_mpi_stmt(get_bb_from_index(fun, bb_pdf_indx_stack.top()))); + inform (loc, "Diverging point might also be later at:"); + bb_pdf_indx_stack.pop(); + } + } } } } @@ -155,12 +267,13 @@ basic_block pass_mpi_collective::get_bb_from_index(function *fun, int index) return bb; } } - + //should not happen return NULL; } +//raise error if there is a collective order error void pass_mpi_collective::raise_warning_mpi_order(function *fun) -{ +{ int mpi_code; int rank; @@ -175,17 +288,18 @@ void pass_mpi_collective::raise_warning_mpi_order(function *fun) int curr_coll_rank; bool coll_rank_diff; int other_coll_rank; + unsigned int diff_index; for (mpi_code = 0; mpi_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; ++mpi_code) { for (rank = 1; rank < collective_max_rank[mpi_code] + 1 ; rank++) { - //printf("mpi_code: %i at rank: %i\n", mpi_code, i); + //printf("mpi_code: %i at rank: %i\n", mpi_code, rank); // DONE: split in 2, get mpi set & find set post dom get_mpi_coll_rank(fun, rank, mpi_code, nodes); //debug_bitmap(nodes); - + for (cursor_code = 0; cursor_code < LAST_AND_UNUSED_MPI_COLLECTIVE_CODE; cursor_code++) @@ -195,16 +309,18 @@ void pass_mpi_collective::raise_warning_mpi_order(function *fun) continue; } - curr_coll_rank = -1; + curr_coll_rank = -1;//other collective being tested against + diff_index = -1; //idx at which another collective call is found before coll_rank_diff = false; EXECUTE_IF_SET_IN_BITMAP(nodes, 0, index, bi) { + other_coll_rank = ((bb_data *) get_bb_from_index(fun, index)->aux) ->collective_rank[cursor_code]; //printf("bb %i as mpi code %i and mpi rank %i\n", - // index, cursor_code, other_coll_rank); + //index, cursor_code, other_coll_rank); if (curr_coll_rank == -1) { curr_coll_rank = other_coll_rank; @@ -212,20 +328,45 @@ void pass_mpi_collective::raise_warning_mpi_order(function *fun) else if (curr_coll_rank != other_coll_rank) { coll_rank_diff = true; + diff_index = index; } } if (coll_rank_diff) { // TODO make better warning messages - printf("======> WARNING !!! ====> MPI " - "Colelctive rank missmatch for collective %s" - " at MPI Collective %s at rank %i\n", - mpi_collective_name[cursor_code], - mpi_collective_name[mpi_code], rank); + //printf("======> WARNING !!! ====> MPI " + // "Collective rank missmatch for collective %s" + // " at MPI Collective %s at rank %i\n", + // mpi_collective_name[cursor_code], + // mpi_collective_name[mpi_code], rank); + + location_t loc = gimple_location( + get_mpi_stmt(get_bb_from_index(fun, diff_index))); + + warning_at (loc + , 0 + , "MPI Collective %s(%i) might not be reachable due to a precedent %s call:" + , mpi_collective_name[mpi_code] + , rank, mpi_collective_name[cursor_code]); + + EXECUTE_IF_SET_IN_BITMAP(nodes, 0, index, bi) + { + if (index!=diff_index) + { + loc = gimple_location( + get_mpi_stmt(get_bb_from_index(fun, index))); + inform (loc + , "reachable %s(%i) without a prior %s call:" + , mpi_collective_name[mpi_code] + , rank, mpi_collective_name[cursor_code]); + } + } } - } + + } + bitmap_clear(nodes); } }