Index: llvm/lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2393,6 +2393,17 @@ if (UsePostInc) IVLimit = SE->getAddExpr(IVLimit, SE->getOne(IVLimit->getType())); + // If computed limit is equal to old limit then do not use SCEV expander + // because it can lost NUW/NSW flags and create extra instructions. + BranchInst *BI = cast(ExitingBB->getTerminator()); + if (ICmpInst *Cmp = dyn_cast(BI->getOperand(0))) { + Value *Limit = Cmp->getOperand(0); + if (!L->isLoopInvariant(Limit)) + Limit = Cmp->getOperand(1); + if (SE->getSCEV(Limit) == IVLimit) + return Limit; + } + // Expand the code for the iteration count. assert(SE->isLoopInvariant(IVLimit, L) && "Computed iteration count is not loop invariant!"); @@ -2401,7 +2412,6 @@ // SCEV expression (IVInit) for a pointer type IV value (IndVar). Type *LimitTy = ExitCount->getType()->isPointerTy() ? IndVar->getType() : ExitCount->getType(); - BranchInst *BI = cast(ExitingBB->getTerminator()); return Rewriter.expandCodeFor(IVLimit, LimitTy, BI); } } Index: llvm/test/Transforms/IndVarSimplify/add_nsw.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/IndVarSimplify/add_nsw.ll @@ -0,0 +1,23 @@ +; RUN: opt -indvars -S %s | FileCheck %s + +target datalayout = "e-p:32:32-i64:64-n8:16:32" + +; CHECK: for.body.preheader: +; CHECK-NOT: add +; CHECK: for.body: + +define void @foo(i32 %a1, i32 %a2) { +entry: + %maxval = add nuw nsw i32 %a1, %a2 + %cmp = icmp slt i32 %maxval, 1 + br i1 %cmp, label %for.end, label %for.body + +for.body: ; preds = %entry, %for.body + %j.02 = phi i32 [ 0, %entry ], [ %add31, %for.body ] + %add31 = add nuw nsw i32 %j.02, 1 + %cmp22 = icmp slt i32 %add31, %maxval + br i1 %cmp22, label %for.body, label %for.end + +for.end: ; preds = %for.body + ret void +} Index: llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll +++ llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll @@ -67,11 +67,9 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] ; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: outer.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[ARG]], -1 ; CHECK-NEXT: br label [[OUTER:%.*]] ; CHECK: outer: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[TMP0]], [[OUTER_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[OUTER_INC:%.*]] ] -; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC]] ], [ 0, [[OUTER_PREHEADER]] ] +; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] @@ -81,14 +79,13 @@ ; CHECK: inner: ; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[INNER_PH]] ], [ [[J_INC:%.*]], [[INNER]] ] ; CHECK-NEXT: [[J_INC]] = add nuw nsw i32 [[J]], 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[J_INC]], [[INDVARS_IV]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[J_INC]], [[SUB3]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] ; CHECK: outer.inc.loopexit: ; CHECK-NEXT: br label [[OUTER_INC]] ; CHECK: outer.inc: ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i32 [[INDVARS_IV]], -1 -; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[I_INC]], [[TMP0]] +; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[I_INC]], [[SUB1]] ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] Index: llvm/test/Transforms/IndVarSimplify/udiv.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/udiv.ll +++ llvm/test/Transforms/IndVarSimplify/udiv.ll @@ -133,6 +133,7 @@ ; CHECK-LABEL: @foo( ; CHECK: for.body.preheader: ; CHECK-NOT: udiv +; CHECK: for.body: define void @foo(double* %p, i64 %n) nounwind { entry: