Index: llvm/lib/Transforms/Utils/SimplifyIndVar.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -1898,6 +1898,10 @@ // to the new (widened) increment. auto *OrigInc = cast(OrigPhi->getIncomingValueForBlock(LatchBlock)); + if (isa(OrigInc) && OrigInc->hasNoSignedWrap()) + WideInc->setHasNoSignedWrap(true); + if (isa(OrigInc) && OrigInc->hasNoUnsignedWrap()) + WideInc->setHasNoUnsignedWrap(true); WideInc->setDebugLoc(OrigInc->getDebugLoc()); } Index: llvm/test/Transforms/IndVarSimplify/AArch64/widen-loop-comp.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/AArch64/widen-loop-comp.ll +++ llvm/test/Transforms/IndVarSimplify/AArch64/widen-loop-comp.ll @@ -275,7 +275,7 @@ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] ; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: br label [[FOR_COND]] ; CHECK: for.end: ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ] @@ -410,7 +410,7 @@ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] ; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 0, [[INDVARS_IV_NEXT]] ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]] ; CHECK: for.end: Index: llvm/test/Transforms/IndVarSimplify/X86/pr27133.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/X86/pr27133.ll +++ llvm/test/Transforms/IndVarSimplify/X86/pr27133.ll @@ -21,7 +21,7 @@ ; CHECK: exit: ; CHECK-NEXT: ret i32 [[C_0_LCSSA]] ; CHECK: for.inc: -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: br label [[FOR_COND]] ; entry: Index: llvm/test/Transforms/IndVarSimplify/keep-nsw-nuw-flag.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/IndVarSimplify/keep-nsw-nuw-flag.ll @@ -0,0 +1,59 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -indvars -S < %s | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-gnu" + +@a = external global [8000 x float], align 64 +@b = external global [8000 x float], align 64 +@c = external global [8000 x float], align 64 + +define float @foo(i32 %arg1, i32 %arg2) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[ARG1:%.*]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[ARG2:%.*]] to i64 +; CHECK-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[BODY:%.*]] +; CHECK: body: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BODY]] ], [ [[TMP0]], [[PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX_A:%.*]] = getelementptr inbounds [8000 x float], [8000 x float]* @a, i64 0, i64 [[INDVARS_IV]] +; CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[ARRAYIDX_A]], align 4 +; CHECK-NEXT: [[ARRAYIDX_B:%.*]] = getelementptr inbounds [8000 x float], [8000 x float]* @b, i64 0, i64 [[INDVARS_IV]] +; CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[ARRAYIDX_B]], align 4 +; CHECK-NEXT: [[ARRAYIDX_C:%.*]] = getelementptr inbounds [8000 x float], [8000 x float]* @c, i64 0, i64 [[INDVARS_IV]] +; CHECK-NEXT: [[FADD:%.*]] = fadd fast float [[TMP2]], [[TMP3]] +; CHECK-NEXT: store float [[FADD]], float* [[ARRAYIDX_C]], align 4 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP1]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], 8000 +; CHECK-NEXT: br i1 [[CMP]], label [[BODY]], label [[CLEANUP:%.*]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: cleanup: +; CHECK-NEXT: br label [[PREHEADER]] +; +entry: + br label %preheader + +preheader: ; preds = %cleanup, %entry + br label %body + +body: ; preds = %body, %preheader + %iv = phi i32 [ %arg1, %preheader ], [ %add, %body ] + %sext = sext i32 %iv to i64 + %arrayidx.a = getelementptr inbounds [8000 x float], [8000 x float]* @a, i64 0, i64 %sext + %0 = load float, float* %arrayidx.a, align 4 + %arrayidx.b = getelementptr inbounds [8000 x float], [8000 x float]* @b, i64 0, i64 %sext + %1 = load float, float* %arrayidx.b, align 4 + %arrayidx.c = getelementptr inbounds [8000 x float], [8000 x float]* @c, i64 0, i64 %sext + %fadd = fadd fast float %0, %1 + store float %fadd, float* %arrayidx.c, align 4 + %add = add nsw i32 %iv, %arg2 + %cmp = icmp slt i32 %add, 8000 + br i1 %cmp, label %body, label %cleanup, !llvm.loop !0 + +cleanup: ; preds = %body + br label %preheader +} + +!0 = distinct !{!0, !1} +!1 = !{!"llvm.loop.mustprogress"} Index: llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll +++ llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll @@ -16,7 +16,7 @@ ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[GID_0]], i64 1 ; CHECK-NEXT: [[ARRAYIDX2115:%.*]] = getelementptr inbounds [15 x i8*], [15 x i8*]* [[PTRIDS]], i64 0, i64 [[INDVARS_IV]] ; CHECK-NEXT: store i8* [[GID_0]], i8** [[ARRAYIDX2115]], align 8 -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: br label [[FOR_COND2106]] ; entry: Index: llvm/test/Transforms/LoopFlatten/widen-iv.ll =================================================================== --- llvm/test/Transforms/LoopFlatten/widen-iv.ll +++ llvm/test/Transforms/LoopFlatten/widen-iv.ll @@ -41,11 +41,11 @@ ; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[FLATTEN_TRUNCIV]] to i64 ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[IDXPROM_US]] ; CHECK-NEXT: tail call void @f(i32* [[ARRAYIDX_US]]) -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw nsw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]] ; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us: -; CHECK-NEXT: [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1 +; CHECK-NEXT: [[INDVAR_NEXT2]] = add nuw nsw i64 [[INDVAR1]], 1 ; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]] ; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] ; CHECK: for.cond.cleanup.loopexit: @@ -132,12 +132,12 @@ ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVAR2]] ; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[ARRAYIDX_US]], align 4 ; CHECK-NEXT: tail call void @g(i32 [[TMP8]]) -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw nsw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[INC_US:%.*]] = add nuw nsw i32 [[J_016_US]], 1 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]] ; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us: -; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1 +; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i64 [[INDVAR2]], 1 ; CHECK-NEXT: [[INC6_US]] = add nuw nsw i32 [[I_018_US]], 1 ; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]] ; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] @@ -240,7 +240,7 @@ ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[IDXPROM_US]] ; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[ARRAYIDX_US]], align 4 ; CHECK-NEXT: tail call void @g(i32 [[TMP4]]) -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]] ; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us: @@ -335,7 +335,7 @@ ; CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[ARRAYIDX_US]], align 2 ; CHECK-NEXT: [[ADD5_US:%.*]] = add i16 [[TMP4]], [[VAL:%.*]] ; CHECK-NEXT: store i16 [[ADD5_US]], i16* [[ARRAYIDX_US]], align 2 -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND1_FOR_INC7_CRIT_EDGE_US]] ; CHECK: for.cond1.for.inc7_crit_edge.us: @@ -420,7 +420,7 @@ ; CHECK-NEXT: [[ADD_US:%.*]] = add i8 [[TMP3]], [[MUL_US]] ; CHECK-NEXT: [[CONV14_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i32 ; CHECK-NEXT: [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[CMP6_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] ; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us: @@ -529,7 +529,7 @@ ; CHECK-NEXT: [[CALL20_US:%.*]] = tail call i32 @use_16(i16 [[CONV15_US]]) ; CHECK-NEXT: [[CONV21_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i64 ; CHECK-NEXT: [[CALL22_US:%.*]] = tail call i32 @use_64(i64 [[CONV21_US]]) -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[CMP6_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] ; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us: @@ -643,7 +643,7 @@ ; CHECK-NEXT: [[CALL18_US:%.*]] = tail call i32 @use_16(i16 [[FLATTEN_TRUNCIV]]) ; CHECK-NEXT: [[CONV19_US:%.*]] = sext i16 [[FLATTEN_TRUNCIV]] to i64 ; CHECK-NEXT: [[CALL20_US:%.*]] = tail call i32 @use_64(i64 [[CONV19_US]]) -; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add nuw nsw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[CMP6_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]] ; CHECK-NEXT: br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] ; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us: Index: llvm/test/Transforms/LoopFlatten/widen-iv2.ll =================================================================== --- llvm/test/Transforms/LoopFlatten/widen-iv2.ll +++ llvm/test/Transforms/LoopFlatten/widen-iv2.ll @@ -45,12 +45,12 @@ ; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64 ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[TMP4]], i64 [[TMP7]] ; CHECK-NEXT: store i32 32, i32* [[ARRAYIDX_US]], align 4 -; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 +; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i64 [[INDVAR]], 1 ; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[J_014_US]], 1 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP1]] ; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY3_US]], label [[FOR_COND1_FOR_INC4_CRIT_EDGE_US]] ; CHECK: for.cond1.for.inc4_crit_edge.us: -; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1 +; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i64 [[INDVAR2]], 1 ; CHECK-NEXT: [[INC5_US]] = add nuw nsw i32 [[I_016_US]], 1 ; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[TMP3]] ; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END6_LOOPEXIT:%.*]] Index: llvm/test/Transforms/LoopFlatten/widen-iv3.ll =================================================================== --- llvm/test/Transforms/LoopFlatten/widen-iv3.ll +++ llvm/test/Transforms/LoopFlatten/widen-iv3.ll @@ -1,5 +1,5 @@ - ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py + ; RUN: opt < %s -S -loop-flatten \ ; RUN: -verify-loop-info -verify-dom-info -verify-scev -verify | \ ; RUN: FileCheck %s --check-prefix=CHECK @@ -25,13 +25,13 @@ ; CHECK-NEXT: ret i16 [[ADD5_LCSSA_LCSSA]] ; CHECK: for.cond.cleanup3: ; CHECK-NEXT: [[ADD5_LCSSA]] = phi i16 [ [[ADD5:%.*]], [[FOR_BODY4]] ] -; CHECK-NEXT: [[INDVAR_NEXT3]] = add i32 [[INDVAR2]], 1 +; CHECK-NEXT: [[INDVAR_NEXT3]] = add nuw nsw i32 [[INDVAR2]], 1 ; CHECK-NEXT: [[INC7]] = add nuw nsw i16 [[I_013]], 1 ; CHECK-NEXT: [[EXITCOND14_NOT:%.*]] = icmp eq i32 [[INDVAR_NEXT3]], 4 ; CHECK-NEXT: br i1 [[EXITCOND14_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER]] ; CHECK: for.body4: ; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ [[INDVAR_NEXT:%.*]], [[FOR_BODY4]] ], [ 0, [[FOR_COND1_PREHEADER]] ] -; CHECK-NEXT: [[J_011:%.*]] = phi i16 [ 0, [[FOR_COND1_PREHEADER]] ] +; CHECK-NEXT: [[J_011:%.*]] = phi i16 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INC:%.*]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[SUM_110:%.*]] = phi i16 [ [[SUM_012]], [[FOR_COND1_PREHEADER]] ], [ [[ADD5]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i32 [[INDVAR]], [[TMP0]] ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[J_011]], [[MUL]] @@ -39,8 +39,8 @@ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [64 x i16], [64 x i16]* @v, i16 0, i16 [[TMP3]] ; CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[ARRAYIDX]], align 1 ; CHECK-NEXT: [[ADD5]] = add nsw i16 [[TMP4]], [[SUM_110]] -; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1 -; CHECK-NEXT: [[INC:%.*]] = add nuw nsw i16 [[J_011]], 1 +; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i32 [[INDVAR]], 1 +; CHECK-NEXT: [[INC]] = add nuw nsw i16 [[J_011]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INDVAR_NEXT]], 16 ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP3]], label [[FOR_BODY4]] ;