Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -4988,6 +4988,18 @@ SCEV::NoWrapFlags Result = SCEV::FlagAnyWrap; + if (!AR->hasNoSelfWrap()) { + const SCEV *BECount = getConstantMaxBackedgeTakenCount(AR->getLoop()); + if (const SCEVConstant *BECountMax = dyn_cast(BECount)) { + ConstantRange StepCR = getSignedRange(AR->getStepRecurrence(*this)); + APInt BECountAP = BECountMax->getAPInt(); + unsigned NoOverflowBitWidth = + BECountAP.getActiveBits() + StepCR.getMinSignedBits(); + if (NoOverflowBitWidth <= getTypeSizeInBits(AR->getType())) + Result = ScalarEvolution::setFlags(Result, SCEV::FlagNW); + } + } + if (!AR->hasNoSignedWrap()) { ConstantRange AddRecRange = getSignedRange(AR); ConstantRange IncRange = getSignedRange(AR->getStepRecurrence(*this)); Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -6769,14 +6769,7 @@ // iteration. The simplest case to consider is a candidate IV which is // narrower than the trip count (and thus original IV), but this can // also happen due to non-unit strides on the candidate IVs. - // TODO: This check should be replaceable with PostInc->hasNoSelfWrap(), - // but in practice we appear to be missing inference for cases we should - // be able to catch. - ConstantRange StepCR = SE.getSignedRange(AddRec->getStepRecurrence(SE)); - ConstantRange BECountCR = SE.getUnsignedRange(BECount); - unsigned NoOverflowBitWidth = BECountCR.getActiveBits() + StepCR.getMinSignedBits(); - unsigned ARBitWidth = SE.getTypeSizeInBits(AddRec->getType()); - if (NoOverflowBitWidth > ARBitWidth) + if (!AddRec->hasNoSelfWrap()) continue; const SCEVAddRecExpr *PostInc = AddRec->getPostIncExpr(SE); Index: llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll +++ llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll @@ -94,7 +94,7 @@ ; CHECK: %s3 = add i32 %is1, %phi5 ; CHECK-NEXT: --> {{{{}}(59 + (2 * %a) + %b),+,6}<%loop1>,+,2}<%loop2> ; CHECK: %s4 = add i32 %phi2, %is2 -; CHECK-NEXT: --> {{{{}}(159 + (2 * %b)),+,2}<%loop1>,+,6}<%loop2> +; CHECK-NEXT: --> {{{{}}(159 + (2 * %b)),+,2}<%loop1>,+,6}<%loop2> ; CHECK: %s5 = add i32 %is1, %is2 ; CHECK-NEXT: --> {{{{}}(165 + (2 * %a) + (2 * %b)),+,6}<%loop1>,+,6}<%loop2> ; CHECK: %s6 = add i32 %is2, %is1 Index: llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll +++ llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll @@ -1633,9 +1633,9 @@ ; CHECK-LABEL: 'ptr_induction_ult_1' ; CHECK-NEXT: Classifying expressions for: @ptr_induction_ult_1 ; CHECK-NEXT: %ptr.iv = phi ptr [ %ptr.iv.next, %loop ], [ %a, %entry ] -; CHECK-NEXT: --> {%a,+,4}<%loop> U: full-set S: full-set Exits: %a LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {%a,+,4}<%loop> U: full-set S: full-set Exits: %a LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i64 1 -; CHECK-NEXT: --> {(4 + %a),+,4}<%loop> U: full-set S: full-set Exits: (4 + %a) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {(4 + %a),+,4}<%loop> U: full-set S: full-set Exits: (4 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @ptr_induction_ult_1 ; CHECK-NEXT: Loop %loop: backedge-taken count is 0 ; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 0 @@ -1686,18 +1686,17 @@ ret i32 0 } -; TODO: The pointer induction variable can be implied No Self Wrap. define void @gep_addrec_nw(ptr %a) { ; CHECK-LABEL: 'gep_addrec_nw' ; CHECK-NEXT: Classifying expressions for: @gep_addrec_nw ; CHECK-NEXT: %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ] -; CHECK-NEXT: --> {%a,+,4}<%for.body> U: full-set S: full-set Exits: (1512 + %a) LoopDispositions: { %for.body: Computable } +; CHECK-NEXT: --> {%a,+,4}<%for.body> U: full-set S: full-set Exits: (1512 + %a) LoopDispositions: { %for.body: Computable } ; CHECK-NEXT: %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ 379, %entry ] ; CHECK-NEXT: --> {379,+,-1}<%for.body> U: [1,380) S: [1,380) Exits: 1 LoopDispositions: { %for.body: Computable } ; CHECK-NEXT: %lsr.iv.next = add nsw i64 %lsr.iv, -1 ; CHECK-NEXT: --> {378,+,-1}<%for.body> U: [0,379) S: [0,379) Exits: 0 LoopDispositions: { %for.body: Computable } ; CHECK-NEXT: %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 -; CHECK-NEXT: --> {(4 + %a),+,4}<%for.body> U: full-set S: full-set Exits: (1516 + %a) LoopDispositions: { %for.body: Computable } +; CHECK-NEXT: --> {(4 + %a),+,4}<%for.body> U: full-set S: full-set Exits: (1516 + %a) LoopDispositions: { %for.body: Computable } ; CHECK-NEXT: Determining loop execution counts for: @gep_addrec_nw ; CHECK-NEXT: Loop %for.body: backedge-taken count is 378 ; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is 378 Index: llvm/test/Transforms/LoopRotate/pr51981-scev-problem.ll =================================================================== --- llvm/test/Transforms/LoopRotate/pr51981-scev-problem.ll +++ llvm/test/Transforms/LoopRotate/pr51981-scev-problem.ll @@ -22,7 +22,7 @@ ; CHECK-SCEV: %narrow = trunc i32 %wide to i16 ; CHECK-SCEV: --> (trunc i32 %wide to i16) U: full-set S: full-set Exits: <> LoopDispositions: { %loop.outer.header: Variant, %loop.inner: Invariant } ; CHECK-SCEV: %iv = phi i16 [ %narrow, %loop.inner.ph ], [ %iv.plus, %loop.inner ] -; CHECK-SCEV: --> {(trunc i32 %wide to i16),+,1}<%loop.inner> U: full-set S: full-set Exits: (-1 + (700 umax (1 + (trunc i32 %wide to i16)))) LoopDispositions: { %loop.inner: Computable, %loop.outer.header: Variant } +; CHECK-SCEV: --> {(trunc i32 %wide to i16),+,1}<%loop.inner> U: full-set S: full-set Exits: (-1 + (700 umax (1 + (trunc i32 %wide to i16)))) LoopDispositions: { %loop.inner: Computable, %loop.outer.header: Variant } ; ; CHECK-SCEV: Classifying expressions for: @test_function ; CHECK-SCEV: %wide1 = load i32, ptr @offset, align 1 @@ -32,7 +32,7 @@ ; CHECK-SCEV: %narrow = trunc i32 %wide2 to i16 ; CHECK-SCEV: --> (trunc i32 %wide2 to i16) U: full-set S: full-set Exits: <> LoopDispositions: { %loop.inner.ph: Variant, %loop.inner: Invariant } ; CHECK-SCEV: %iv = phi i16 [ %narrow, %loop.inner.ph ], [ %iv.plus, %loop.inner ] -; CHECK-SCEV: --> {(trunc i32 %wide2 to i16),+,1}<%loop.inner> U: full-set S: full-set Exits: (-1 + (700 umax (1 + (trunc i32 %wide2 to i16)))) LoopDispositions: { %loop.inner: Computable, %loop.inner.ph: Variant } +; CHECK-SCEV: --> {(trunc i32 %wide2 to i16),+,1}<%loop.inner> U: full-set S: full-set Exits: (-1 + (700 umax (1 + (trunc i32 %wide2 to i16)))) LoopDispositions: { %loop.inner: Computable, %loop.inner.ph: Variant } @offset = external dso_local global i32, align 1 Index: llvm/test/Transforms/LoopVersioning/lcssa.ll =================================================================== --- llvm/test/Transforms/LoopVersioning/lcssa.ll +++ llvm/test/Transforms/LoopVersioning/lcssa.ll @@ -56,7 +56,6 @@ ; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult i8* [[SCEVGEP]], [[SCEVGEP2]] ; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult i8* [[LS2_21_PROMOTED]], [[SCEVGEP1]] ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] -; CHECK-NEXT: [[SCEVGEP3:%.*]] = getelementptr i8, i8* [[LS1_20_PROMOTED]], i64 -1 ; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label %bb1.ph.lver.orig, label %bb1.ph ; CHECK: bb1.ph.lver.orig: ;