Index: llvm/include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- llvm/include/llvm/Analysis/LoopInfoImpl.h +++ llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -217,7 +217,7 @@ BlockT *Header = getHeader(); BlockT *Latch = nullptr; for (const auto Pred : children>(Header)) { - if (contains(Pred)) { + if (Latch != Pred && contains(Pred)) { if (Latch) return nullptr; Latch = Pred; Index: llvm/lib/Transforms/Utils/LoopSimplify.cpp =================================================================== --- llvm/lib/Transforms/Utils/LoopSimplify.cpp +++ llvm/lib/Transforms/Utils/LoopSimplify.cpp @@ -20,7 +20,8 @@ // by the loop header). This simplifies transformations such as store-sinking // that are built into LICM. // -// This pass also guarantees that loops will have exactly one backedge. +// This pass also guarantees that loops will have exactly one latch block. This +// implies a single backedge, although it may be represented as a multi-edge. // // Indirectbr instructions introduce several complications. If the loop // contains or is entered by an indirectbr instruction, it may not be possible Index: llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp =================================================================== --- llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -1334,6 +1334,7 @@ Twine(IVName) + ".iv"); // Create the step instructions and populate the PHI. + Value *IncV = nullptr; for (pred_iterator HPI = HPB; HPI != HPE; ++HPI) { BasicBlock *Pred = *HPI; @@ -1346,10 +1347,12 @@ // Create a step value and add it to the PHI. // If IVIncInsertLoop is non-null and equal to the addrec's loop, insert the // instructions at IVIncInsertPos. - Instruction *InsertPos = L == IVIncInsertLoop ? - IVIncInsertPos : Pred->getTerminator(); - Builder.SetInsertPoint(InsertPos); - Value *IncV = expandIVInc(PN, StepV, L, ExpandTy, IntTy, useSubtract); + if (!IncV) { + Instruction *InsertPos = L == IVIncInsertLoop ? + IVIncInsertPos : Pred->getTerminator(); + Builder.SetInsertPoint(InsertPos); + IncV = expandIVInc(PN, StepV, L, ExpandTy, IntTy, useSubtract); + } if (isa(IncV)) { if (IncrementIsNUW) Index: llvm/test/Transforms/LoopSimplify/basictest.ll =================================================================== --- llvm/test/Transforms/LoopSimplify/basictest.ll +++ llvm/test/Transforms/LoopSimplify/basictest.ll @@ -43,18 +43,16 @@ ; CHECK: loop.preheader: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[B:%.*]] = load volatile i8, i8* [[B_PTR:%.*]] -; CHECK-NEXT: switch i8 [[B]], label [[LOOP_BACKEDGE:%.*]] [ +; CHECK-NEXT: [[B:%.*]] = load volatile i8, i8* [[B_PTR:%.*]], align 1 +; CHECK-NEXT: switch i8 [[B]], label [[LOOP]] [ ; CHECK-NEXT: i8 0, label [[EXIT_A_LOOPEXIT:%.*]] ; CHECK-NEXT: i8 1, label [[EXIT_B_LOOPEXIT:%.*]] -; CHECK-NEXT: i8 2, label [[LOOP_BACKEDGE]] +; CHECK-NEXT: i8 2, label [[LOOP]] ; CHECK-NEXT: i8 3, label [[EXIT_A_LOOPEXIT]] -; CHECK-NEXT: i8 4, label [[LOOP_BACKEDGE]] +; CHECK-NEXT: i8 4, label [[LOOP]] ; CHECK-NEXT: i8 5, label [[EXIT_A_LOOPEXIT]] -; CHECK-NEXT: i8 6, label [[LOOP_BACKEDGE]] +; CHECK-NEXT: i8 6, label [[LOOP]] ; CHECK-NEXT: ] -; CHECK: loop.backedge: -; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit.a.loopexit: ; CHECK-NEXT: br label [[EXIT_A]] ; CHECK: exit.a: @@ -98,13 +96,13 @@ ; CHECK: loop.ph: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[C1:%.*]] = load volatile i1, i1* [[PTR:%.*]] +; CHECK-NEXT: [[C1:%.*]] = load volatile i1, i1* [[PTR:%.*]], align 1 ; CHECK-NEXT: br i1 [[C1]], label [[LOOP_BODY1:%.*]], label [[DEDICATED_EXIT1:%.*]] ; CHECK: loop.body1: -; CHECK-NEXT: [[C2:%.*]] = load volatile i1, i1* [[PTR]] +; CHECK-NEXT: [[C2:%.*]] = load volatile i1, i1* [[PTR]], align 1 ; CHECK-NEXT: br i1 [[C2]], label [[LOOP_BODY2:%.*]], label [[NON_DEDICATED_EXIT_LOOPEXIT:%.*]] ; CHECK: loop.body2: -; CHECK-NEXT: [[C3:%.*]] = load volatile i1, i1* [[PTR]] +; CHECK-NEXT: [[C3:%.*]] = load volatile i1, i1* [[PTR]], align 1 ; CHECK-NEXT: br i1 [[C3]], label [[LOOP_BACKEDGE:%.*]], label [[DEDICATED_EXIT2:%.*]] ; CHECK: loop.backedge: ; CHECK-NEXT: br label [[LOOP_HEADER]] @@ -163,17 +161,17 @@ ; CHECK: loop.ph: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[ADDR1:%.*]] = load volatile i8*, i8** [[ADDR_PTR:%.*]] +; CHECK-NEXT: [[ADDR1:%.*]] = load volatile i8*, i8** [[ADDR_PTR:%.*]], align 8 ; CHECK-NEXT: indirectbr i8* [[ADDR1]], [label [[LOOP_BODY1:%.*]], label %exit.a] ; CHECK: loop.body1: -; CHECK-NEXT: [[B:%.*]] = load volatile i8, i8* [[PTR:%.*]] +; CHECK-NEXT: [[B:%.*]] = load volatile i8, i8* [[PTR:%.*]], align 1 ; CHECK-NEXT: switch i8 [[B]], label [[LOOP_BODY2:%.*]] [ ; CHECK-NEXT: i8 0, label [[EXIT_A]] ; CHECK-NEXT: i8 1, label [[EXIT_B_LOOPEXIT:%.*]] ; CHECK-NEXT: i8 2, label [[EXIT_C]] ; CHECK-NEXT: ] ; CHECK: loop.body2: -; CHECK-NEXT: [[ADDR2:%.*]] = load volatile i8*, i8** [[ADDR_PTR]] +; CHECK-NEXT: [[ADDR2:%.*]] = load volatile i8*, i8** [[ADDR_PTR]], align 8 ; CHECK-NEXT: indirectbr i8* [[ADDR2]], [label [[LOOP_BACKEDGE:%.*]], label %exit.c] ; CHECK: loop.backedge: ; CHECK-NEXT: br label [[LOOP_HEADER]] Index: llvm/test/Transforms/LoopStrengthReduce/multi-edge-latch.ll =================================================================== --- llvm/test/Transforms/LoopStrengthReduce/multi-edge-latch.ll +++ llvm/test/Transforms/LoopStrengthReduce/multi-edge-latch.ll @@ -14,15 +14,13 @@ ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[P_BASE:%.*]], i64 1 ; CHECK-NEXT: br label [[WHILE_BODY:%.*]] ; CHECK: while.body: -; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP1:%.*]], [[WHILE_BODY_BACKEDGE:%.*]] ], [ [[SCEVGEP]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP]], [[WHILE_BODY_PREHEADER]] ], [ [[SCEVGEP1:%.*]], [[WHILE_BODY]] ], [ [[SCEVGEP1]], [[WHILE_BODY]] ] ; CHECK-NEXT: [[Y:%.*]] = load i8, i8* [[LSR_IV]], align 1 +; CHECK-NEXT: [[SCEVGEP1]] = getelementptr i8, i8* [[LSR_IV]], i64 1 ; CHECK-NEXT: switch i8 [[Y]], label [[WHILE_END_LOOPEXIT:%.*]] [ -; CHECK-NEXT: i8 10, label [[WHILE_BODY_BACKEDGE]] -; CHECK-NEXT: i8 20, label [[WHILE_BODY_BACKEDGE]] +; CHECK-NEXT: i8 10, label [[WHILE_BODY]] +; CHECK-NEXT: i8 20, label [[WHILE_BODY]] ; CHECK-NEXT: ] -; CHECK: while.body.backedge: -; CHECK-NEXT: [[SCEVGEP1]] = getelementptr i8, i8* [[LSR_IV]], i64 1 -; CHECK-NEXT: br label [[WHILE_BODY]] ; CHECK: while.end.loopexit: ; CHECK-NEXT: br label [[WHILE_END]] ; CHECK: while.end: Index: llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll @@ -1329,14 +1329,11 @@ ; CHECK-NEXT: br label %for.cond ; CHECK:for.cond: -; CHECK-NEXT: switch i32 %cleanup.dest.slot.0, label %for.cond.backedge [ -; CHECK-NEXT: i32 0, label %for.cond.backedge +; CHECK-NEXT: switch i32 %cleanup.dest.slot.0, label %for.cond [ +; CHECK-NEXT: i32 0, label %for.cond ; CHECK-NEXT: i32 2, label %loop.loopexit ; CHECK-NEXT: ] -; CHECK:for.cond.backedge: -; CHECK-NEXT: br label %for.cond - ; CHECK:loop.loopexit: ; CHECK-NEXT: unreachable