diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -919,6 +919,13 @@ } private: + bool checkIsHoistable(const Instruction &I) { + return (isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I)); + } + bool parallelCodeMotion() { bool Changed = false; const unsigned CallbackCalleeOperand = 2; @@ -933,46 +940,79 @@ return false; SmallDenseMap> BB2PRMap; - SmallPtrSet InstructionsToBeMoved; + SmallPtrSet PreviousInstructions; + SmallPtrSet InvariantInstructions; auto SelectCMInst = [&](Use &U, Function &F) { CallInst *CI = getCallIfRegularCall(U); if (!CI) return false; - auto *Fn = dyn_cast( + const Function *Fn = dyn_cast( CI->getArgOperand(CallbackCalleeOperand)->stripPointerCasts()); - for (BasicBlock &BB : Fn->getBasicBlockList()) { - for (Instruction &I : BB) { + const DominatorTree *DT = + OMPInfoCache.getAnalysisResultForFunction(*Fn); - /// check for constant operand operations - auto CheckConstantOperands = [&](Instruction &I) { - int operandCount = I.getNumOperands(); - for (int i = 0; i < operandCount; i++) { - if (!dyn_cast(I.getOperand(i))) { - return false; + // TODO Need to check segfault with this call + AAResults *AA = OMPInfoCache.getAAResultsForFunction(*Fn); + + BasicBlock *Root = DT->getRoot(); + ReversePostOrderTraversal RPOT(Root); + for (auto *BB : RPOT) { + for (Instruction &I : make_early_inc_range(*BB)) { + + auto HasInvariantOperands = [&](Instruction &I) { + return all_of(I.operands(), [&](Value *V) { + if (const Instruction *I = dyn_cast(V)) + return !(I->getFunction()->getName() == (*Fn).getName()) || + InvariantInstructions.contains(I); + return true; + }); + }; + + auto checkMemoryOperationsAliased = [&](Instruction &PresI) { + if (!(isa(PresI) || isa(PresI))) { + return false; + } + for (auto PrevI : PreviousInstructions) { + if (LoadInst *LI = dyn_cast(&PresI)) { + if (StoreInst *SI = dyn_cast(PrevI)) { + if (!(*AA).alias(LI->getPointerOperand(), + SI->getPointerOperand())) { + continue; + } + } + } else if (LoadInst *LI = dyn_cast(PrevI)) { + if (StoreInst *SI = dyn_cast(&PresI)) { + if (!(*AA).alias(LI->getPointerOperand(), + SI->getPointerOperand())) { + continue; + } + } } + PreviousInstructions.insert(&PresI); + return true; } - return true; + PreviousInstructions.insert(&PresI); + return false; }; - /// choosing instruction for code motion - if (!I.mayThrow() && !I.mayReadOrWriteMemory() && - isSafeToSpeculativelyExecute(&I) && CheckConstantOperands(I)) { - InstructionsToBeMoved.insert(&I); - NumOpenMPParallelInstructionsForCodeMotion++; + if (checkIsHoistable(I) && !I.mayThrow() && + isSafeToSpeculativelyExecute(&I) && HasInvariantOperands(I) && + !checkMemoryOperationsAliased(I)) { + InvariantInstructions.insert(&I); + NumOpenMPParallelRegionsForCodeMotion++; continue; } } } - if (!InstructionsToBeMoved.empty()) { + if (!InvariantInstructions.empty()) { Changed = true; } - /// moves instructions before the callsite for __kmpc_fork_call - for (auto instruction : InstructionsToBeMoved) { + for (auto instruction : InvariantInstructions) { instruction->moveBefore(CI); } return false; @@ -980,9 +1020,10 @@ RFI.foreachUse(SCC, SelectCMInst); - for (auto instr : InstructionsToBeMoved) { - LLVM_DEBUG(dbgs() << TAG << "Instruction for CodeMotion : " - << instr->dump() << "\n"); + LLVM_DEBUG(dbgs() << TAG << "Instructions for CM : " + << "\n"); + for (auto CME : InvariantInstructions) { + LLVM_DEBUG(CME->dump()); } return Changed; }