/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/CollectiveList.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "parcoach/CollectiveList.h" |
2 | | |
3 | | #include "PTACallGraph.h" |
4 | | #include "Utils.h" |
5 | | |
6 | | #include "llvm/IR/BasicBlock.h" |
7 | | #include "llvm/Support/raw_ostream.h" |
8 | | |
9 | | #include <sstream> |
10 | | |
11 | | using namespace llvm; |
12 | | namespace parcoach { |
13 | | namespace { |
14 | | // Little helper to tell us if we should ignore the collective. |
15 | | // We basically ignore the collective if the Communicator is not null and if |
16 | | // it matches the communicator in the call instruction. |
17 | 7.08k | bool shouldIgnore(CallInst const &CI, Collective const &Coll, Value *Comm) { |
18 | 7.08k | if (!isa<MPICollective>(Coll) || !Comm) { |
19 | | // If it's not an mpi collective, or if we don't have a communicator, |
20 | | // we definitely shouldn't ignore it! |
21 | 247 | return false; |
22 | 247 | } |
23 | 6.83k | MPICollective const &MPIColl = cast<MPICollective>(Coll); |
24 | 6.83k | Value *CommForCollective = MPIColl.getCommunicator(CI); |
25 | 6.83k | return CommForCollective != nullptr && CommForCollective != Comm; |
26 | 7.08k | } |
27 | | } // namespace |
28 | | |
29 | 4.97k | bool CollectiveList::navs() const { |
30 | 4.97k | if (List_.empty()) { |
31 | 1 | return false; |
32 | 1 | } |
33 | 4.97k | return List_.front()->navs(); |
34 | 4.97k | } |
35 | | |
36 | | CollectiveList::CollectiveList(CollectiveList const &From) |
37 | 2.94k | : LoopHeader_(From.LoopHeader_) { |
38 | 2.94k | for (auto const &Elem : From.List_) { |
39 | 162 | List_.emplace_back(Elem->copy()); |
40 | 162 | } |
41 | 2.94k | } |
42 | | |
43 | | CollectiveList::CollectiveList(BasicBlock *Header, |
44 | | CollectiveList const &LoopList) |
45 | 468 | : CollectiveList(LoopList) { |
46 | | // Override the loop header after copy construction. |
47 | 468 | LoopHeader_ = Header; |
48 | 468 | } |
49 | | |
50 | | void CollectiveList::add(CollectiveList const &Other, |
51 | 13.4k | std::insert_iterator<ListTy> Inserter) { |
52 | 13.4k | if (!Other.List_.empty()) { |
53 | 12.0k | if (Other.LoopHeader_) { |
54 | 15 | Inserter = std::make_unique<CollListElement>(Other); |
55 | 12.0k | } else { |
56 | 17.1k | for (auto const &ListElem : Other.List_) { |
57 | 17.1k | Inserter = ListElem->copy(); |
58 | 17.1k | } |
59 | 12.0k | } |
60 | 12.0k | } |
61 | 13.4k | } |
62 | | |
63 | 12.5k | void CollectiveList::extendWith(CollectiveList const &Other) { |
64 | 12.5k | add(Other, std::inserter(List_, List_.end())); |
65 | 12.5k | } |
66 | | |
67 | 963 | void CollectiveList::prependWith(CollectiveList const &Other) { |
68 | 963 | add(Other, std::inserter(List_, List_.begin())); |
69 | 963 | } |
70 | | |
71 | 10.5k | std::string CollectiveList::toString() const { |
72 | 10.5k | std::string Ret; |
73 | 10.5k | raw_string_ostream Err(Ret); |
74 | 10.5k | if (LoopHeader_) { |
75 | 18 | Err << "*"; |
76 | 18 | LoopHeader_.value()->printAsOperand(Err, false); |
77 | 18 | } |
78 | 10.5k | Err << "("; |
79 | 10.5k | bool First = true; |
80 | 18.4k | for (auto const &Elem : List_) { |
81 | 18.4k | if (!First) { |
82 | 7.91k | Err << ", "; |
83 | 7.91k | } |
84 | 18.4k | Err << Elem->toString(); |
85 | 18.4k | First = false; |
86 | 18.4k | } |
87 | 10.5k | Err << ")"; |
88 | 10.5k | return Ret; |
89 | 10.5k | } |
90 | | |
91 | | CollectiveList CollectiveList::CreateFromBB(BBToCollListMap const &CollLists, |
92 | | PTACallGraph const &PTACG, |
93 | | bool NeighborsAreNAVS, |
94 | | llvm::BasicBlock &BB, |
95 | 15.2k | llvm::Value *Comm) { |
96 | 15.2k | CollectiveList Current; |
97 | 15.2k | if (NeighborsAreNAVS) { |
98 | 798 | Current.extendWith<NavsElement>(); |
99 | 798 | return Current; |
100 | 798 | } |
101 | | |
102 | 50.3k | auto ActOnFunction = [&](CallInst &CI, Function const &F) { |
103 | 50.3k | if (auto const *Coll = Collective::find(F)) { |
104 | 7.08k | if (!shouldIgnore(CI, *Coll, Comm)) { |
105 | 6.93k | Current.extendWith<CollElement>(*Coll); |
106 | 6.93k | } |
107 | 43.3k | } else if (CollLists.count(&F.getEntryBlock()) != 0) { |
108 | 62 | auto const &ListForFunc = CollLists.find(&F.getEntryBlock())->second; |
109 | 62 | Current.extendWith(ListForFunc); |
110 | 62 | } |
111 | 50.3k | }; |
112 | 178k | auto IsCI = [](Instruction &I) { return isa<CallInst>(I); }; |
113 | 50.3k | for (auto &I : make_filter_range(BB, IsCI)) { |
114 | 50.3k | CallInst &CI = cast<CallInst>(I); |
115 | 50.3k | if (!CI.getCalledFunction()) { |
116 | | // Iterate over functions which may be called |
117 | 3 | auto Found = PTACG.getIndirectCallMap().find(&CI); |
118 | 3 | if (Found == PTACG.getIndirectCallMap().end()) { |
119 | 0 | continue; |
120 | 0 | } |
121 | 6 | for (Function const *MayCall : Found->second) { |
122 | 6 | if (isIntrinsicDbgFunction(MayCall)) { |
123 | 0 | continue; |
124 | 0 | } |
125 | | // FIXME: think about that: currently it pushes *all* the possible |
126 | | // collective called by *all* the may call functions. |
127 | 6 | ActOnFunction(CI, *MayCall); |
128 | 6 | } |
129 | 50.3k | } else { |
130 | 50.3k | ActOnFunction(CI, *CI.getCalledFunction()); |
131 | 50.3k | } |
132 | 50.3k | } |
133 | 14.4k | return Current; |
134 | 15.2k | } |
135 | | |
136 | | } // namespace parcoach |