diff --git a/lib/Transforms/Scalar/LoopIndexSplit.cpp b/lib/Transforms/Scalar/LoopIndexSplit.cpp index 047e6563779d..6a2c7587f6e0 100644 --- a/lib/Transforms/Scalar/LoopIndexSplit.cpp +++ b/lib/Transforms/Scalar/LoopIndexSplit.cpp @@ -585,16 +585,7 @@ bool LoopIndexSplit::processOneIterationLoop(SplitInfo &SD) { // only when index variable is equal to split value. IndVar->replaceAllUsesWith(SD.SplitValue); - // Remove Latch to Header edge. - BasicBlock *LatchSucc = NULL; - Header->removePredecessor(Latch); - for (succ_iterator SI = succ_begin(Latch), E = succ_end(Latch); - SI != E; ++SI) { - if (Header != *SI) - LatchSucc = *SI; - } - BR->setUnconditionalDest(LatchSucc); - + Instruction *LTerminator = Latch->getTerminator(); Instruction *Terminator = Header->getTerminator(); Value *ExitValue = ExitCondition->getOperand(ExitValueNum); @@ -606,12 +597,14 @@ bool LoopIndexSplit::processOneIterationLoop(SplitInfo &SD) { // c2 = icmp ult i32 SplitValue, ExitValue // and i32 c1, c2 bool SignedPredicate = ExitCondition->isSignedPredicate(); + CmpInst::Predicate C2Predicate = ExitCondition->getPredicate(); + if (LTerminator->getOperand(0) != Header) + C2Predicate = CmpInst::getInversePredicate(C2Predicate); Instruction *C1 = new ICmpInst(SignedPredicate ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, SD.SplitValue, StartValue, "lisplit", Terminator); - Instruction *C2 = new ICmpInst(SignedPredicate ? - ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, + Instruction *C2 = new ICmpInst(C2Predicate, SD.SplitValue, ExitValue, "lisplit", Terminator); Instruction *NSplitCond = BinaryOperator::CreateAnd(C1, C2, "lisplit", @@ -619,9 +612,18 @@ bool LoopIndexSplit::processOneIterationLoop(SplitInfo &SD) { SD.SplitCondition->replaceAllUsesWith(NSplitCond); SD.SplitCondition->eraseFromParent(); + // Remove Latch to Header edge. + BasicBlock *LatchSucc = NULL; + Header->removePredecessor(Latch); + for (succ_iterator SI = succ_begin(Latch), E = succ_end(Latch); + SI != E; ++SI) { + if (Header != *SI) + LatchSucc = *SI; + } + BR->setUnconditionalDest(LatchSucc); + // Now, clear latch block. Remove instructions that are responsible // to increment induction variable. - Instruction *LTerminator = Latch->getTerminator(); for (BasicBlock::iterator LB = Latch->begin(), LE = Latch->end(); LB != LE; ) { Instruction *I = LB; diff --git a/test/Transforms/LoopIndexSplit/2008-10-10-OneIteration.ll b/test/Transforms/LoopIndexSplit/2008-10-10-OneIteration.ll new file mode 100644 index 000000000000..7c0d207d3ea4 --- /dev/null +++ b/test/Transforms/LoopIndexSplit/2008-10-10-OneIteration.ll @@ -0,0 +1,66 @@ +; RUN: llvm-as < %s | opt -loop-index-split | llvm-dis | grep sle | count 1 +; PR 2869 + +@w = external global [2 x [2 x i32]] ; <[2 x [2 x i32]]*> [#uses=5] + +declare i32 @f() nounwind + +define i32 @main() noreturn nounwind { +entry: + br label %bb1.i.outer + +bb1.i.outer: ; preds = %bb5.i, %entry + %i.0.reg2mem.0.ph.i.ph = phi i32 [ 0, %entry ], [ %4, %bb5.i ] ; [#uses=3] + br label %bb1.i + +bb1.i: ; preds = %bb3.i, %bb1.i.outer + %j.0.reg2mem.0.i = phi i32 [ %2, %bb3.i ], [ 0, %bb1.i.outer ] ; [#uses=3] + %0 = icmp eq i32 %i.0.reg2mem.0.ph.i.ph, %j.0.reg2mem.0.i ; [#uses=1] + br i1 %0, label %bb2.i, label %bb3.i + +bb2.i: ; preds = %bb1.i + %1 = getelementptr [2 x [2 x i32]]* @w, i32 0, i32 %i.0.reg2mem.0.ph.i.ph, i32 %j.0.reg2mem.0.i ; [#uses=1] + store i32 1, i32* %1, align 4 + br label %bb3.i + +bb3.i: ; preds = %bb2.i, %bb1.i + %2 = add i32 %j.0.reg2mem.0.i, 1 ; [#uses=2] + %3 = icmp sgt i32 %2, 1 ; [#uses=1] + br i1 %3, label %bb5.i, label %bb1.i + +bb5.i: ; preds = %bb3.i + %4 = add i32 %i.0.reg2mem.0.ph.i.ph, 1 ; [#uses=2] + %5 = icmp sgt i32 %4, 1 ; [#uses=1] + br i1 %5, label %f.exit, label %bb1.i.outer + +f.exit: ; preds = %bb5.i + %6 = load i32* getelementptr ([2 x [2 x i32]]* @w, i32 0, i32 0, i32 0), align 4 ; [#uses=1] + %7 = icmp eq i32 %6, 1 ; [#uses=1] + br i1 %7, label %bb, label %bb3 + +bb: ; preds = %f.exit + %8 = load i32* getelementptr ([2 x [2 x i32]]* @w, i32 0, i32 1, i32 1), align 4 ; [#uses=1] + %9 = icmp eq i32 %8, 1 ; [#uses=1] + br i1 %9, label %bb1, label %bb3 + +bb1: ; preds = %bb + %10 = load i32* getelementptr ([2 x [2 x i32]]* @w, i32 0, i32 1, i32 0), align 4 ; [#uses=1] + %11 = icmp eq i32 %10, 0 ; [#uses=1] + br i1 %11, label %bb2, label %bb3 + +bb2: ; preds = %bb1 + %12 = load i32* getelementptr ([2 x [2 x i32]]* @w, i32 0, i32 0, i32 1), align 4 ; [#uses=1] + %13 = icmp eq i32 %12, 0 ; [#uses=1] + br i1 %13, label %bb4, label %bb3 + +bb3: ; preds = %bb2, %bb1, %bb, %f.exit + tail call void @abort() noreturn nounwind + unreachable + +bb4: ; preds = %bb2 + ret i32 0 +} + +declare void @abort() noreturn nounwind + +declare void @exit(i32) noreturn nounwind