Coverage Report

Created: 2023-10-30 17:15

/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/OpenMPInstr.cpp
Line
Count
Source
1
#include "OpenMPInstr.h"
2
3
#include "Utils.h"
4
#include "parcoach/MemoryRegion.h"
5
6
#include "llvm/IR/InstIterator.h"
7
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
8
9
#define DEBUG_TYPE "openmp-instr"
10
11
using namespace llvm;
12
namespace parcoach {
13
14
// ValueMap<Instruction *, Instruction *> PrepareOpenMPInstr::NewInst2oldInst;
15
16
PreservedAnalyses PrepareOpenMPInstr::run(Module &M,
17
15
                                          ModuleAnalysisManager &AM) {
18
15
  TimeTraceScope TTS("PrepareOpenMPInstr");
19
15
  LLVM_DEBUG(dbgs() << "Running PrepareOpenMPInstr\n");
20
21
979
  auto IsCandidateCall = [&](Instruction &I) {
22
979
    if (auto *CI = dyn_cast<CallInst>(&I)) {
23
309
      auto *Callee = CI->getCalledFunction();
24
309
      if (Callee && Callee->getName() == "__kmpc_fork_call") {
25
16
        return true;
26
16
      }
27
309
    }
28
963
    return false;
29
979
  };
30
31
143
  for (Function &F : M) {
32
    // Get all calls to be replaced (only __kmpc_fork_call is handled for now).
33
143
    auto Instructions = make_filter_range(instructions(F), IsCandidateCall);
34
    // Use early inc range to be able to replace the instruction on the fly.
35
143
    for (auto &I : make_early_inc_range(Instructions)) {
36
16
      CallInst &CI = cast<CallInst>(I);
37
      // Operand 2 contains the outlined function
38
16
      Value *Op2 = CI.getOperand(2);
39
16
      Function *OutlinedFunc = dyn_cast<Function>(Op2);
40
16
      assert(OutlinedFunc && "can't cast kmp_fork_call arg");
41
42
16
      LLVM_DEBUG(dbgs() << OutlinedFunc->getName() << "\n");
43
44
16
      unsigned CallNbOps = CI.getNumOperands();
45
46
16
      SmallVector<Value *, 8> NewArgs;
47
48
      // map 2 firsts operands of CI to null
49
48
      for (unsigned I = 0; I < 2; I++) {
50
32
        Type *ArgTy = OutlinedFunc->getArg(I)->getType();
51
32
        Value *Val = Constant::getNullValue(ArgTy);
52
32
        NewArgs.push_back(Val);
53
32
      }
54
55
      //  op 3 to nbops-1 are shared variables
56
25
      for (unsigned I = 3; I < CallNbOps - 1; I++) {
57
9
        MemReg::func2SharedOmpVar[OutlinedFunc].insert(CI.getOperand(I));
58
9
        NewArgs.push_back(CI.getOperand(I));
59
9
      }
60
61
16
      CallInst *NewCI = CallInst::Create(OutlinedFunc, NewArgs);
62
16
      NewCI->setCallingConv(OutlinedFunc->getCallingConv());
63
16
      ReplaceInstWithInst(&CI, NewCI);
64
16
    }
65
143
  }
66
15
  return PreservedAnalyses::none();
67
15
}
68
69
// We use to do the following to revert OpenMP transformations, but I have yet
70
// to understand why we would bother reverting.
71
/*
72
void ParcoachInstr::revertOmpTransformation() {
73
  for (auto I : ompNewInst2oldInst) {
74
    Instruction *newInst = I.first;
75
    Instruction *oldInst = I.second;
76
    ReplaceInstWithInst(newInst, oldInst);
77
  }
78
}
79
*/
80
} // namespace parcoach