Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -97,7 +97,7 @@ const LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE); static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, - const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, + const Loop *CurLoop, LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE, bool FreeInLoop); static bool isSafeToExecuteUnconditionally(Instruction &Inst, const DominatorTree *DT, @@ -857,8 +857,13 @@ static bool canSplitPredecessors(PHINode *PN) { BasicBlock *BB = PN->getParent(); - if (!BB->canSplitPredecessors()) + // FIXME: it's not impossible to split LandingPad blocks, but it require + // updating BlockColors for all offspring blocks. By skipping such corner + // case, we can make updating BlockColors after splitting predecessor fairly + // simple. + if (BB->getFirstNonPHI()->isEHPad()) return false; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { BasicBlock *BBPred = *PI; if (isa(BBPred->getTerminator())) @@ -868,7 +873,8 @@ } static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT, - LoopInfo *LI, const Loop *CurLoop) { + LoopInfo *LI, const Loop *CurLoop, + LoopSafetyInfo *SafetyInfo) { #ifndef NDEBUG SmallVector ExitBlocks; CurLoop->getUniqueExitBlocks(ExitBlocks); @@ -910,13 +916,27 @@ // LE: // %p = phi [%p1, %LE.split], [%p2, %LE.split2] // + + auto &BlockColors = SafetyInfo->BlockColors; SmallSetVector PredBBs(pred_begin(ExitBB), pred_end(ExitBB)); + + assert(!ExitBB->getFirstNonPHI()->isEHPad() && + "Unexpected exit block split."); + while (!PredBBs.empty()) { BasicBlock *PredBB = *PredBBs.begin(); assert(CurLoop->contains(PredBB) && "Expect all predecessors are in the loop"); - if (PN->getBasicBlockIndex(PredBB) >= 0) - SplitBlockPredecessors(ExitBB, PredBB, ".split.loop.exit", DT, LI, true); + if (PN->getBasicBlockIndex(PredBB) >= 0) { + BasicBlock *NewPred = SplitBlockPredecessors( + ExitBB, PredBB, ".split.loop.exit", DT, LI, true); + + // Sine we don't allow splitting EH-blocks, we can simply assign + // predecessor's color to the new block. + if (!BlockColors.empty()) + BlockColors[NewPred] = BlockColors[PredBB]; + } + PredBBs.remove(PredBB); } } @@ -927,7 +947,7 @@ /// position, and may either delete it or move it to outside of the loop. /// static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, - const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, + const Loop *CurLoop, LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE, bool FreeInLoop) { DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n"); ORE->emit([&]() { @@ -980,7 +1000,7 @@ // Split predecessors of the PHI so that we can make users trivially // replacable. - splitPredecessorsOfLoopExit(PN, DT, LI, CurLoop); + splitPredecessorsOfLoopExit(PN, DT, LI, CurLoop, SafetyInfo); // Should rebuild the iterators, as they may be invalidated by // splitPredecessorsOfLoopExit(). Index: test/Transforms/LICM/sinking.ll =================================================================== --- test/Transforms/LICM/sinking.ll +++ test/Transforms/LICM/sinking.ll @@ -670,6 +670,51 @@ ret void } +; The sinkable call should be sunk into an exit block split. After splitting +; the exit block, BlockColor for new blocks should be added properly so +; that we should be able to access valid ColorVector. +; +; CHECK-LABEL:@test21_pr36184 +; CHECK-LABEL: Loop +; CHECK-NOT: %sinkableCall +; CHECK-LABEL:Out.split.loop.exit +; CHECK: %sinkableCall +define i32 @test21_pr36184(i8* %P, i32* %s, i1 %b, i32 %v1) personality i32 (...)* @__CxxFrameHandler3 { +entry: + br label %while.cond + +while.cond: + br i1 %b, label %try.cont, label %while.body + +while.body: + invoke void @may_throw() + to label %try.cont unwind label %lpadBB +lpadBB: + landingpad { i8*, i32 } + catch i8* null + ret i32 1 + +try.cont: + br i1 undef, label %while.cond, label %end1 + +end1: + br label %loop.ph + +loop.ph: + br label %Loop + +Loop: + %sinkableCall = call i32 @strlen( i8* %P ) readonly + br i1 undef, label %ContLoop, label %Out + +ContLoop: + br i1 undef, label %Loop, label %Out + +Out: + %idx = phi i32 [ %sinkableCall, %Loop ], [0, %ContLoop ] + ret i32 %idx +} + declare void @may_throw() declare void @may_throw2() declare i32 @__CxxFrameHandler3(...)