/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/Collectives.cpp
Line | Count | Source |
1 | | #include "parcoach/Collectives.h" |
2 | | #include "parcoach/Options.h" |
3 | | |
4 | | #include "llvm/ADT/StringMap.h" |
5 | | #include "llvm/IR/Function.h" |
6 | | #include "llvm/IR/Instructions.h" |
7 | | |
8 | | namespace parcoach { |
9 | | using namespace llvm; |
10 | | namespace { |
11 | | |
12 | | struct Registry { |
13 | 425k | static auto const &get() { |
14 | 425k | static Registry Instance; |
15 | 425k | return Instance.Data; |
16 | 425k | } |
17 | | |
18 | 1.76k | ~Registry() { |
19 | 70.4k | for (auto const &ItC : Data) { |
20 | 70.4k | delete ItC.second; |
21 | 70.4k | } |
22 | 1.76k | } |
23 | | |
24 | | private: |
25 | | // NOTE: we must use dynamically allocated memory here, storing a Collective |
26 | | // would not allocate enough space for derived types. |
27 | | // We unfortunately can't use a unique_ptr as initializer lists don't have |
28 | | // a move semantic. |
29 | | // Therefore we use this trick of having a singleton instance with a custom |
30 | | // destructor. |
31 | 1.76k | Registry() = default; |
32 | | StringMap<Collective const *> const Data{ |
33 | | #define MPI_COLLECTIVE(Name, CommArgId) \ |
34 | | {#Name, new MPICollective(Collective::Kind::C_##Name, #Name, CommArgId)}, |
35 | | #include "parcoach/MPIRegistry.def" |
36 | | #define COLLECTIVE(Name, FunctionName, Type) \ |
37 | | {#Name, new Type##Collective(Collective::Kind::C_##Name, #FunctionName)}, |
38 | | #ifdef PARCOACH_ENABLE_OPENMP |
39 | | #define OMP_COLLECTIVE(Name) COLLECTIVE(Name, Name, OMP) |
40 | | #include "parcoach/OMPRegistry.def" |
41 | | #endif |
42 | | #ifdef PARCOACH_ENABLE_UPC |
43 | | #define UPC_COLLECTIVE(Name) COLLECTIVE(Name, Name, UPC) |
44 | | #include "parcoach/UPCRegistry.def" |
45 | | #endif |
46 | | #ifdef PARCOACH_ENABLE_CUDA |
47 | | #define CUDA_COLLECTIVE(Name, FunctionName) COLLECTIVE(Name, FunctionName, Cuda) |
48 | | #include "parcoach/CUDARegistry.def" |
49 | | #endif |
50 | | #undef COLLECTIVE |
51 | | }; |
52 | | }; |
53 | | |
54 | | } // namespace |
55 | | |
56 | 39.0k | bool Collective::enabled() const { return Options::get().isActivated(P_); } |
57 | | |
58 | 212k | Collective const *Collective::find(Function const &F) { |
59 | 212k | auto It = Registry::get().find(F.getName()); |
60 | 212k | if (It != Registry::get().end() && It->second->enabled()) { |
61 | 39.0k | return It->second; |
62 | 39.0k | } |
63 | 173k | return {}; |
64 | 212k | } |
65 | | |
66 | 53.8k | bool Collective::isCollective(Function const &F) { |
67 | 53.8k | return Collective::find(F) != nullptr; |
68 | 53.8k | } |
69 | | |
70 | 18.8k | Value *MPICollective::getCommunicator(CallInst const &CI) const { |
71 | | // NOTE: we expect CI to actually call "this" collective, but we don't assert |
72 | | // for it since it may be an indirect call. |
73 | 18.8k | if (CommArgId < 0) { |
74 | 3.35k | return nullptr; |
75 | 3.35k | } |
76 | 15.4k | Value *Comm = CI.getArgOperand(CommArgId); |
77 | | // This is flaky, we should do a better job at tracking communicator aliases. |
78 | 30.1k | while (auto *PtrToComm = dyn_cast<LoadInst>(Comm)) { |
79 | 14.7k | Comm = PtrToComm->getPointerOperand(); |
80 | 14.7k | } |
81 | 15.4k | return Comm; |
82 | 18.8k | } |
83 | | } // namespace parcoach |