/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 |