Index: lib/Transforms/Utils/LoopSimplify.cpp =================================================================== --- lib/Transforms/Utils/LoopSimplify.cpp +++ lib/Transforms/Utils/LoopSimplify.cpp @@ -67,6 +67,7 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopUtils.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" using namespace llvm; #define DEBUG_TYPE "loop-simplify" @@ -339,6 +340,75 @@ } } + // Split edges to exit blocks from the inner loop, if they emerged in the + // process of separating the outer one. + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + SmallSetVector ExitBlockSet(ExitBlocks.begin(), + ExitBlocks.end()); + for (BasicBlock *ExitBlock : ExitBlockSet) { + for (pred_iterator PI = pred_begin(ExitBlock), PE = pred_end(ExitBlock); + PI != PE; ++PI) + // Must be exactly this loop: no subloops, parent loops, or non-loop preds + // allowed. + if (!L->contains(*PI)) { + rewriteLoopExitBlock(L, ExitBlock, DT, LI, PreserveLCSSA); + break; + } + } + + if (PreserveLCSSA) { + // Fix LCSSA form for L. Some values, which previously were only used inside + // L, can now be used in NewOuter loop. We need to insert phi-nodes for them + // in corresponding exit blocks. + // We've just rewritten the exit blocks, so we have to construct + // ExitBlocksSet again. + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + SmallSetVector ExitBlockSet(ExitBlocks.begin(), + ExitBlocks.end()); + + // Go through all instructions in NewBB and check if they are using operands + // from the inner loop. In this case we'll need to insert LCSSA phi-nodes to + // preserve LCSSA. + for (Instruction &NewI : *NewBB) { + PHINode *PN = dyn_cast(&NewI); + if (!PN) + break; + for (unsigned Idx = 0, E = PN->getNumIncomingValues(); Idx != E; ++Idx) { + Instruction *I = dyn_cast(PN->getIncomingValue(Idx)); + if (!I || !L->contains(I)) + continue; + + // We've found a value from L used in OuterL. Let's insert phi-nodes at + // the corresponding exits blocks and run SSAUpdate to use these values. + SSAUpdater SSAUpdate; + SSAUpdate.Initialize(I->getType(), I->getName()); + for (BasicBlock *ExitBB : ExitBlockSet) { + if (SSAUpdate.HasValueForBlock(ExitBB)) + continue; + if (!DT->dominates(I->getParent(), ExitBB)) + continue; + + // We've found the exit block where we need to insert the phi-node. + // Create it and register in SSAUpdater. + PHINode *NewPN = PHINode::Create( + PN->getType(), 1, I->getName() + ".lcssa", &ExitBB->front()); + for (BasicBlock *PredBB : predecessors(ExitBB)) + NewPN->addIncoming(I, PredBB); + SSAUpdate.AddAvailableValue(ExitBB, NewPN); + } + + // Rewrite all uses of I in PN with the new values. We do this for all + // operands and not only for the current one to avoid creating multiple + // LCSSA phi-nodes for the same value. + for (unsigned IdxToRewrite = Idx; IdxToRewrite != E; ++IdxToRewrite) + if (PN->getIncomingValue(IdxToRewrite) == I) + SSAUpdate.RewriteUse(PN->getOperandUse(IdxToRewrite)); + } + } + } + return NewOuter; } Index: test/Transforms/LoopSimplify/pr28272.ll =================================================================== --- /dev/null +++ test/Transforms/LoopSimplify/pr28272.ll @@ -0,0 +1,70 @@ +; RUN: opt < %s -lcssa -loop-unroll -S | FileCheck %s +target triple = "x86_64-unknown-linux-gnu" + +; Check that we don't crash on this test. +; LoopSimplify is invoked by LoopUnroll. +; CHECK-LABEL: @foo +define void @foo() { +entry: + br label %header + +header: + br label %loop1 + +loop1: + br i1 true, label %loop1, label %bb43 + +bb43: + %a = phi i32 [ undef, %loop1 ], [ 0, %bb45 ], [ %a, %bb54 ] + %b = phi i32 [ 0, %loop1 ], [ 1, %bb54 ], [ %c, %bb45 ] + br i1 true, label %bb114, label %header + +bb114: + %c = add i32 0, 1 + br i1 true, label %bb45, label %bb54 + +bb45: + br label %bb43 + +bb54: + br label %bb43 +} + +; CHECK-LABEL: @foo2 +define void @foo2() { +entry: + br label %outer + +outer.loopexit: + br label %outer + +outer: + br label %loop1 + +loop1: + br i1 true, label %loop1, label %loop2.preheader + +loop2.preheader: + %a.ph = phi i32 [ undef, %loop1 ] + %b.ph = phi i32 [ 0, %loop1 ] + br label %loop2 + +loop2: + %a = phi i32 [ 0, %loop2.if.true ], [ %a, %loop2.if.false ], [ %a.ph, %loop2.preheader ], [0, %bb] + %b = phi i32 [ 1, %loop2.if.false ], [ %c, %loop2.if.true ], [ %b.ph, %loop2.preheader ], [%c, %bb] + br i1 true, label %loop2.if, label %outer.loopexit + +loop2.if: + %c = add i32 0, 1 + switch i32 undef, label %loop2.if.false [i32 0, label %loop2.if.true + i32 1, label %bb] + +loop2.if.true: + br i1 undef, label %loop2, label %bb + +loop2.if.false: + br label %loop2 + +bb: + br label %loop2 +}