diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -201,15 +201,19 @@ /// convert the logical iteration variable to the loop counter variable in the /// loop body. /// - /// \param Loc The insert and source location description. + /// \param Loc The insert and source location description. The insert + /// location can be between two instructions or the end of a + /// degenerate block (e.g. a BB under construction). /// \param BodyGenCB Callback that will generate the loop body code. /// \param TripCount Number of iterations the loop body is executed. + /// \param Name Base name used to derive BB and instruction names. /// /// \returns An object representing the created control flow structure which /// can be used for loop-associated directives. CanonicalLoopInfo *createCanonicalLoop(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, - Value *TripCount); + Value *TripCount, + const Twine &Name = "loop"); /// Generator for the control flow structure of an OpenMP canonical loop. /// @@ -252,13 +256,20 @@ /// and Stop are signed integers. /// \param InclusiveStop Whether \p Stop itself is a valid value for the loop /// counter. + /// \param ComputeIP Insertion point for instructions computing the trip + /// count. Can be used to ensure the trip count is available + /// at the outermost loop of a loop nest. If not set, + /// defaults to the preheader of the generated loop. + /// \param Name Base name used to derive BB and instruction names. /// /// \returns An object representing the created control flow structure which /// can be used for loop-associated directives. CanonicalLoopInfo *createCanonicalLoop(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *Start, Value *Stop, Value *Step, - bool IsSigned, bool InclusiveStop); + bool IsSigned, bool InclusiveStop, + InsertPointTy ComputeIP = {}, + const Twine &Name = "loop"); /// Modifies the canonical loop to be a statically-scheduled workshare loop. /// @@ -644,6 +655,28 @@ /// \param CriticalName Name of the critical region. /// Value *getOMPCriticalRegionLock(StringRef CriticalName); + + /// Create the control flow structure of a canonical OpenMP loop. + /// + /// The emitted loop will be disconnected, i.e. no edge to the loop's + /// preheader and no terminator in the AfterBB. The OpenMPIRBuilder's + /// IRBuilder location is not preserved. + /// + /// \param DL DebugLoc used for the instructions in the skeleton. + /// \param TripCount Value to be used for the trip count. + /// \param F Function in which to insert the BasicBlocks. + /// \param PreInsertBefore Where to insert BBs that execute before the body, + /// typically the body itself. + /// \param PostInsertBefore Where to insert BBs that execute after the body. + /// \param Name Base name used to derive BB + /// and instruction names. + /// + /// \returns The CanonicalLoopInfo that represents the emitted loop. + CanonicalLoopInfo *createLoopSkeleton(DebugLoc DL, Value *TripCount, + Function *F, + BasicBlock *PreInsertBefore, + BasicBlock *PostInsertBefore, + const Twine &Name = {}); }; /// Class to represented the control flow structure of an OpenMP canonical loop. @@ -693,9 +726,6 @@ BasicBlock *Exit; BasicBlock *After; - /// Delete this loop if unused. - void eraseFromParent(); - public: /// The preheader ensures that there is only a single edge entering the loop. /// Code that must be execute before any loop iteration can be emitted here, @@ -748,6 +778,11 @@ return IndVarPHI; } + /// Return the insertion point for user code in the body. + OpenMPIRBuilder::InsertPointTy getBodyIP() const { + return {Body, Body->begin()}; + }; + /// Return the insertion point for user code after the loop. OpenMPIRBuilder::InsertPointTy getAfterIP() const { return {After, After->begin()}; diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -858,44 +858,43 @@ /*Conditional*/ true, /*hasFinalize*/ true); } -CanonicalLoopInfo * -OpenMPIRBuilder::createCanonicalLoop(const LocationDescription &Loc, - LoopBodyGenCallbackTy BodyGenCB, - Value *TripCount) { - BasicBlock *BB = Loc.IP.getBlock(); - BasicBlock *NextBB = BB->getNextNode(); - Function *F = BB->getParent(); +CanonicalLoopInfo *OpenMPIRBuilder::createLoopSkeleton( + DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, + BasicBlock *PostInsertBefore, const Twine &Name) { + Module *M = F->getParent(); + LLVMContext &Ctx = M->getContext(); Type *IndVarTy = TripCount->getType(); // Create the basic block structure. BasicBlock *Preheader = - BasicBlock::Create(M.getContext(), "omp_for.preheader", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".preheader", F, PreInsertBefore); BasicBlock *Header = - BasicBlock::Create(M.getContext(), "omp_for.header", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".header", F, PreInsertBefore); BasicBlock *Cond = - BasicBlock::Create(M.getContext(), "omp_for.cond", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".cond", F, PreInsertBefore); BasicBlock *Body = - BasicBlock::Create(M.getContext(), "omp_for.body", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".body", F, PreInsertBefore); BasicBlock *Latch = - BasicBlock::Create(M.getContext(), "omp_for.inc", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".inc", F, PostInsertBefore); BasicBlock *Exit = - BasicBlock::Create(M.getContext(), "omp_for.exit", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".exit", F, PostInsertBefore); BasicBlock *After = - BasicBlock::Create(M.getContext(), "omp_for.after", F, NextBB); + BasicBlock::Create(Ctx, "omp_" + Name + ".after", F, PostInsertBefore); - updateToLocation(Loc); - Builder.CreateBr(Preheader); + // Use specified DebugLoc for new instructions. + Builder.SetCurrentDebugLocation(DL); Builder.SetInsertPoint(Preheader); Builder.CreateBr(Header); Builder.SetInsertPoint(Header); - PHINode *IndVarPHI = Builder.CreatePHI(IndVarTy, 2, "omp_for.iv"); + PHINode *IndVarPHI = Builder.CreatePHI(IndVarTy, 2, "omp_" + Name + ".iv"); IndVarPHI->addIncoming(ConstantInt::get(IndVarTy, 0), Preheader); Builder.CreateBr(Cond); Builder.SetInsertPoint(Cond); - Value *Cmp = Builder.CreateICmpULT(IndVarPHI, TripCount, "omp_for.cmp"); + Value *Cmp = + Builder.CreateICmpULT(IndVarPHI, TripCount, "omp_" + Name + ".cmp"); Builder.CreateCondBr(Cmp, Body, Exit); Builder.SetInsertPoint(Body); @@ -903,16 +902,13 @@ Builder.SetInsertPoint(Latch); Value *Next = Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1), - "omp_for.next", /*HasNUW=*/true); + "omp_" + Name + ".next", /*HasNUW=*/true); Builder.CreateBr(Header); IndVarPHI->addIncoming(Next, Latch); Builder.SetInsertPoint(Exit); Builder.CreateBr(After); - // After all control flow has been created, insert the body user code. - BodyGenCB(InsertPointTy(Body, Body->begin()), IndVarPHI); - // Remember and return the canonical control flow. LoopInfos.emplace_front(); CanonicalLoopInfo *CL = &LoopInfos.front(); @@ -933,9 +929,43 @@ return CL; } +CanonicalLoopInfo * +OpenMPIRBuilder::createCanonicalLoop(const LocationDescription &Loc, + LoopBodyGenCallbackTy BodyGenCB, + Value *TripCount, const Twine &Name) { + BasicBlock *BB = Loc.IP.getBlock(); + BasicBlock *NextBB = BB->getNextNode(); + + CanonicalLoopInfo *CL = createLoopSkeleton(Loc.DL, TripCount, BB->getParent(), + NextBB, NextBB, Name); + BasicBlock *After = CL->getAfter(); + + // If location is not set, don't connect the loop. + if (updateToLocation(Loc)) { + // Split the loop at the insertion point: Branch to the preheader and move + // every following instruction to after the loop (the After BB). Also, the + // new successor is the loop's after block. + Builder.CreateBr(CL->Preheader); + After->getInstList().splice(After->begin(), BB->getInstList(), + Builder.GetInsertPoint(), BB->end()); + After->replaceSuccessorsPhiUsesWith(BB, After); + } + + // Emit the body content. We do it after connecting the loop to the CFG to + // avoid that the callback encounters degenerate BBs. + BodyGenCB(CL->getBodyIP(), CL->getIndVar()); + +#ifndef NDEBUG + CL->assertOK(); +#endif + return CL; +} + CanonicalLoopInfo *OpenMPIRBuilder::createCanonicalLoop( const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, - Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop) { + Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, + InsertPointTy ComputeIP, const Twine &Name) { + // Consider the following difficulties (assuming 8-bit signed integers): // * Adding \p Step to the loop counter which passes \p Stop may overflow: // DO I = 1, 100, 50 @@ -947,7 +977,9 @@ assert(IndVarTy == Stop->getType() && "Stop type mismatch"); assert(IndVarTy == Step->getType() && "Step type mismatch"); - updateToLocation(Loc); + LocationDescription ComputeLoc = + ComputeIP.isSet() ? LocationDescription(ComputeIP, Loc.DL) : Loc; + updateToLocation(ComputeLoc); ConstantInt *Zero = ConstantInt::get(IndVarTy, 0); ConstantInt *One = ConstantInt::get(IndVarTy, 1); @@ -988,7 +1020,8 @@ InclusiveStop ? CmpInst::ICMP_ULT : CmpInst::ICMP_ULE, Span, Incr); CountIfLooping = Builder.CreateSelect(OneCmp, One, CountIfTwo); } - Value *TripCount = Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping); + Value *TripCount = Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping, + "omp_" + Name + ".tripcount"); auto BodyGen = [=](InsertPointTy CodeGenIP, Value *IV) { Builder.restoreIP(CodeGenIP); @@ -996,7 +1029,8 @@ Value *IndVar = Builder.CreateAdd(Span, Start); BodyGenCB(Builder.saveIP(), IndVar); }; - return createCanonicalLoop(Builder.saveIP(), BodyGen, TripCount); + LocationDescription LoopLoc = ComputeIP.isSet() ? Loc.IP : Builder.saveIP(); + return createCanonicalLoop(LoopLoc, BodyGen, TripCount, Name); } // Returns an LLVM function to call for initializing loop bounds using OpenMP @@ -1112,20 +1146,6 @@ return CLI; } -void CanonicalLoopInfo::eraseFromParent() { - assert(IsValid && "can only erase previously valid loop cfg"); - IsValid = false; - - SmallVector BBsToRemove{Header, Cond, Latch, Exit}; - SmallVector InstsToRemove; - - // Only remove preheader if not re-purposed somewhere else. - if (Preheader->getNumUses() == 0) - BBsToRemove.push_back(Preheader); - - DeleteDeadBlocks(BBsToRemove); -} - OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCopyPrivate(const LocationDescription &Loc, llvm::Value *BufSize, llvm::Value *CpyBuf,