Coverage Report

Created: 2023-10-30 17:15

/builds/2mk6rsew/0/parcoach/parcoach/src/rma/LocalConcurrencyAnalysis.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "parcoach/RMAPasses.h"
2
3
#include "llvm/Analysis/AliasAnalysis.h"
4
#include "llvm/IR/Function.h"
5
#include "llvm/IR/InstIterator.h"
6
7
#include <deque>
8
9
using namespace llvm;
10
11
namespace parcoach::rma {
12
namespace {
13
class LCDAnalysis {
14
  enum Color { WHITE, GREY, BLACK };
15
  enum ACCESS { READ, WRITE };
16
  static enum ACCESS getInstructionType(Instruction *I);
17
  using BBColorMap = DenseMap<BasicBlock const *, Color>;
18
  using BBMap = DenseMap<BasicBlock const *, bool>;
19
  using BBMemMap = std::map<BasicBlock *, ValueMap<Value *, Instruction *>>;
20
  BBColorMap ColorMap;
21
  BBMap LheaderMap;
22
  BBMap LlatchMap;
23
  BBMemMap BBToMemAccess;
24
  FunctionAnalysisManager &FAM;
25
  LocalConcurrencyVector Results;
26
27
public:
28
55
  LCDAnalysis(FunctionAnalysisManager &FAM) : FAM(FAM){};
29
55
  LocalConcurrencyVector takeResults() {
30
55
    LocalConcurrencyVector Ret;
31
55
    std::swap(Results, Ret);
32
55
    return Ret;
33
55
  }
34
  void analyze(Function *F);
35
  void analyzeBB(BasicBlock *B);
36
  void bfsLoop(Loop *L);
37
  bool mustWait(BasicBlock *BB);
38
  bool mustWaitLoop(llvm::BasicBlock *BB, Loop *L);
39
};
40
41
// Get the memory access from the instruction
42
// We consider only local accesses here
43
66
enum LCDAnalysis::ACCESS LCDAnalysis::getInstructionType(Instruction *I) {
44
66
  if (CallBase *CI = dyn_cast<CallBase>(I)) {
45
52
    if (Function *CalledFunction = CI->getCalledFunction()) {
46
52
      StringRef CalledName = CalledFunction->getName();
47
52
      if (CalledName == "MPI_Get" || CalledName == "mpi_get_") {
48
17
        return WRITE;
49
17
      }
50
35
      if (CalledName == "MPI_Put" || CalledName == "mpi_put_") {
51
35
        return READ;
52
35
      }
53
35
    }
54
52
  } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
55
6
    return WRITE;
56
8
  } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
57
8
    return READ;
58
8
  }
59
  // Default return
60
0
  return READ;
61
66
}
62
63
// Store the memory accesses - we keep the memory which is a value and the last
64
// instruction accessing this memory address
65
// Later: Check interprocedural information
66
// Later: keep the accesses per window
67
488
void LCDAnalysis::analyzeBB(BasicBlock *BB) {
68
488
  Function *F = BB->getParent();
69
488
  AAResults &AA = FAM.getResult<AAManager>(*F);
70
71
4.68k
  for (Instruction &Inst : *BB) {
72
4.68k
    DebugLoc Dbg = Inst.getDebugLoc(); // get debug infos
73
4.68k
    Value *Mem = NULL;
74
4.68k
    bool IsLoadOrStore = false;
75
76
    // (1) Get memory access
77
4.68k
    if (CallBase *CI = dyn_cast<CallBase>(&Inst)) {
78
      // ci->print(errs());
79
      // errs() << "\n";
80
1.50k
      if (Function *CalledFunction = CI->getCalledFunction()) {
81
1.50k
        StringRef CalledName = CalledFunction->getName();
82
        // errs() << "Calledfunction = " << calledFunction->getName() << "\n";
83
1.50k
        if ((CalledName == "MPI_Get") || (CalledName == "MPI_Put") ||
84
1.50k
            (CalledName == "mpi_put_") || (CalledName == "mpi_get_")) {
85
80
          Mem = CI->getArgOperand(0);
86
          // errs() << "!!!!!!!! Found a put / get -> store mem \n";
87
1.42k
        } else if ((CalledName == "MPI_Win_flush") ||
88
1.42k
                   (CalledName == "MPI_Win_flush_all") ||
89
1.42k
                   (CalledName == "MPI_Win_fence") ||
90
1.42k
                   (CalledName == "MPI_Win_flush_local") ||
91
1.42k
                   (CalledName == "MPI_Win_unlock_all") ||
92
1.42k
                   (CalledName == "mpi_win_unlock_all_") ||
93
1.42k
                   (CalledName == "mpi_win_flush_") ||
94
1.42k
                   (CalledName == "mpi_win_flush_all_") ||
95
1.42k
                   (CalledName == "mpi_win_fence_")) {
96
          // GreenErr() << "---> Found a synchro\n";
97
55
          BBToMemAccess[BB].clear();
98
55
        }
99
1.50k
      }
100
3.17k
    } else if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) {
101
483
      Mem = SI->getPointerOperand();
102
483
      IsLoadOrStore = true;
103
2.69k
    } else if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) {
104
826
      Mem = LI->getPointerOperand();
105
826
      IsLoadOrStore = true;
106
826
    }
107
108
4.68k
    if (Mem) {
109
1.38k
      auto PrevAccess = BBToMemAccess[BB].find(Mem);
110
111
      // (2) mem is stored in ValueMap
112
1.38k
      if (BBToMemAccess[BB].count(Mem) != 0) {
113
23
        if (getInstructionType(PrevAccess->second) == WRITE ||
114
23
            getInstructionType(&Inst) == WRITE) {
115
          // Check if we already report this error
116
          // if(ConcurrentAccesses[F].count(inst) == 0 &&
117
          // ConcurrentAccesses[F].count(PrevAccess->second) == 0){
118
13
          Results.insert({&Inst, PrevAccess->second});
119
13
        } else {
120
          /*MagentaErr() << "INFO: Memory address already in map - last access
121
            from instruction: "; PrevAccess->second->print(errs()); errs() <<
122
            "\n";*/
123
10
          if (!IsLoadOrStore) {
124
8
            PrevAccess->second = &Inst;
125
8
          }
126
10
        }
127
        // (2) mem is not stored in ValueMap - check if a memory stored in
128
        // ValueMap alias with mem
129
1.36k
      } else {
130
        // errs() << "(2) No memory access found in ValueMap: " <<
131
        // PrevAccess->second << "\n";
132
        /*GreenErr() << "DEBUG INFO: no PrevAccess found for instruction: ";
133
          inst->print(errs());
134
          errs()  << "\n";*/
135
1.36k
        ValueMap<Value *, Instruction *>::iterator It;
136
        // iterate over the ValueMap to get the first write that alias with mem
137
1.55k
        for (It = BBToMemAccess[BB].begin(); It != BBToMemAccess[BB].end();
138
1.36k
             It++) {
139
185
          if (AA.alias(It->first, Mem) != AliasResult::NoAlias) {
140
            // if(AA.alias(it->first,mem) == AliasResult::MayAlias)
141
            // errs() << "(2) No memory access found in ValueMap: " << it->first
142
            //<< " but found a may alias!\n";
143
            // errs() << "(2) No memory access found in ValueMap: " << it->first
144
            //<< " but found an alias!\n";
145
18
            if (getInstructionType(It->second) == WRITE ||
146
18
                getInstructionType(&Inst) == WRITE) {
147
10
              Results.insert({&Inst, It->second});
148
10
            }
149
18
          }
150
185
        }
151
        // store mem if the instruction is a MPI-RMA
152
1.36k
        if (!IsLoadOrStore) {
153
67
          BBToMemAccess[BB].insert({Mem, &Inst});
154
          /*MagentaErr() << "DEBUG INFO: Add new memory access from instruction:
155
            "; inst->print(errs()); errs() << "\n";*/
156
67
        }
157
1.36k
      }
158
1.38k
    }
159
4.68k
  }
160
488
}
161
162
// If all predecessors have not been set to black, return true otherwise return
163
// false
164
489
bool LCDAnalysis::mustWait(BasicBlock *BB) {
165
489
  if (LheaderMap[BB]) {
166
    // errs() << "is lopp header\n";
167
8
    return false; // ignore loop headers
168
8
  }
169
481
  pred_iterator PI = pred_begin(BB);
170
481
  pred_iterator E = pred_end(BB);
171
1.09k
  for (; PI != E; ++PI) {
172
629
    BasicBlock *Pred = *PI;
173
629
    if (ColorMap[Pred] != BLACK) {
174
17
      return true;
175
17
    }
176
629
  }
177
464
  return false;
178
481
}
179
180
16
bool LCDAnalysis::mustWaitLoop(llvm::BasicBlock *BB, Loop *L) {
181
16
  pred_iterator PI = pred_begin(BB);
182
16
  pred_iterator E = pred_end(BB);
183
24
  for (; PI != E; ++PI) {
184
16
    BasicBlock *Pred = *PI;
185
    // BB is in the only bb in loop
186
16
    if ((Pred == BB) || (LlatchMap[Pred])) {
187
0
      continue;
188
0
    }
189
16
    if (ColorMap[Pred] != BLACK && L->contains(Pred)) {
190
      // printBB(Pred);
191
      // errs() << " is white \n";
192
8
      return true;
193
8
    }
194
16
  }
195
8
  return false;
196
16
}
197
198
8
void LCDAnalysis::bfsLoop(Loop *L) {
199
8
  std::deque<BasicBlock *> Unvisited;
200
8
  BasicBlock *Lheader = L->getHeader();
201
8
  BasicBlock *Llatch = L->getLoopLatch();
202
203
8
  for (Loop *ChildLoop : *L) {
204
0
    bfsLoop(ChildLoop);
205
0
  }
206
  /*errs() << ".. BFS on loop containing ..\n";
207
208
  for (BasicBlock *BB : L->blocks()) {
209
          printBB(BB);
210
  }
211
  errs() << "....\n";
212
  */
213
8
  Unvisited.push_back(Lheader);
214
8
  LheaderMap[L->getHeader()] = true;
215
216
24
  while (!Unvisited.empty()) {
217
16
    BasicBlock *Header = *Unvisited.begin();
218
    // printBB(header);
219
16
    Unvisited.pop_front();
220
221
16
    if (ColorMap[Header] == BLACK) {
222
0
      continue;
223
0
    }
224
16
    if (mustWaitLoop(Header, L) &&
225
16
        Header != L->getHeader()) { // all predecessors have not been seen
226
      // errs() << "must wait..\n";
227
0
      Unvisited.push_back(Header);
228
0
      continue;
229
0
    }
230
231
16
    analyzeBB(Header);
232
16
    ColorMap[Header] = GREY;
233
234
16
    succ_iterator SI = succ_begin(Header);
235
16
    succ_iterator E = succ_end(Header);
236
40
    for (; SI != E; ++SI) {
237
24
      BasicBlock *Succ = *SI;
238
      // Ignore successor not in loop
239
24
      if (!(L->contains(Succ))) {
240
8
        continue;
241
8
      }
242
      // ignore back edge when the loop has already been checked
243
16
      if (LlatchMap[Header] && LheaderMap[Succ]) {
244
0
        continue;
245
0
      }
246
247
      // Succ not seen before
248
16
      if (ColorMap[Succ] == WHITE) {
249
8
        BBToMemAccess[Succ].insert(BBToMemAccess[Header].begin(),
250
8
                                   BBToMemAccess[Header].end());
251
8
        ColorMap[Succ] = GREY;
252
8
        Unvisited.push_back(Succ);
253
        // Succ already seen
254
8
      } else {
255
        // merge the memory accesses from the previous paths - only local errors
256
        // detection
257
        // For latter: report concurrent one-sided
258
8
        BBToMemAccess[Succ].insert(BBToMemAccess[Header].begin(),
259
8
                                   BBToMemAccess[Header].end());
260
8
      }
261
16
    }
262
16
    ColorMap[Header] = BLACK;
263
16
  }
264
  // reset BB colors in loop and ignore backedge for the rest of the BFS
265
16
  for (BasicBlock *BB : L->blocks()) {
266
16
    ColorMap[BB] = WHITE;
267
16
  }
268
8
  LlatchMap[Llatch] = true;
269
8
}
270
271
55
void LCDAnalysis::analyze(Function *F) {
272
  // All BB must be white at the beginning
273
472
  for (BasicBlock &BB : *F) {
274
472
    ColorMap[&BB] = WHITE;
275
472
    LheaderMap[&BB] = false;
276
472
    LlatchMap[&BB] = false;
277
472
  }
278
279
55
  std::deque<BasicBlock *> Unvisited;
280
55
  BasicBlock &Entry = F->getEntryBlock();
281
55
  Unvisited.push_back(&Entry);
282
283
  // errs() << ".. BFS on loops ..\n";
284
55
  auto &LI = FAM.getResult<LoopAnalysis>(*F);
285
55
  for (Loop *L : LI) {
286
8
    bfsLoop(L);
287
8
  }
288
289
  // errs() << ".. BFS ..\n";
290
  //  BFS
291
544
  while (!Unvisited.empty()) {
292
489
    BasicBlock *Header = *Unvisited.begin();
293
    // printBB(header);
294
    // errs() << "has color = " << ColorMap[header] << "\n";
295
489
    Unvisited.pop_front();
296
297
489
    if (ColorMap[Header] == BLACK) {
298
0
      continue;
299
0
    }
300
301
489
    if (mustWait(Header)) { // all predecessors have not been seen
302
      // errs() << " must wait \n";
303
17
      Unvisited.push_back(Header);
304
17
      continue;
305
17
    }
306
307
472
    analyzeBB(Header);
308
472
    ColorMap[Header] = GREY;
309
310
472
    succ_iterator SI = succ_begin(Header);
311
472
    succ_iterator E = succ_end(Header);
312
1.10k
    for (; SI != E; ++SI) {
313
628
      BasicBlock *Succ = *SI;
314
      // ignore back edge
315
628
      if (LlatchMap[Header] && LheaderMap[Succ]) {
316
8
        continue;
317
8
      }
318
      // Succ not seen before
319
620
      if (ColorMap[Succ] == WHITE) {
320
417
        BBToMemAccess[Succ].insert(BBToMemAccess[Header].begin(),
321
417
                                   BBToMemAccess[Header].end());
322
        // analyzeBB(Succ, AA);
323
417
        ColorMap[Succ] = GREY;
324
417
        Unvisited.push_back(Succ);
325
        // Succ already seen
326
417
      } else {
327
        // merge the memory accesses from the previous paths - only local errors
328
        // detection
329
        // For latter: report concurrent one-sided
330
203
        BBToMemAccess[Succ].insert(BBToMemAccess[Header].begin(),
331
203
                                   BBToMemAccess[Header].end());
332
203
      }
333
620
    }
334
472
    ColorMap[Header] = BLACK;
335
472
  }
336
  // Lheaders.clear();
337
55
}
338
} // namespace
339
340
AnalysisKey LocalConcurrencyAnalysis::Key;
341
LocalConcurrencyVector
342
55
LocalConcurrencyAnalysis::run(Function &F, FunctionAnalysisManager &AM) {
343
55
  TimeTraceScope TTS("LocalConcurrencyAnalysis");
344
55
  LCDAnalysis LCD(AM);
345
55
  LCD.analyze(&F);
346
347
55
  return LCD.takeResults();
348
55
}
349
350
} // namespace parcoach::rma