From 914836b1c8b36d4a317ef6c233746f6ec37b57a5 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 23 Aug 2021 17:52:09 -0700 Subject: [PATCH] [SCEV] Infer nsw/nuw from nw for addrecs If we no an addrec doesn't self-wrap, the increment is strictly positive, and the start value is the smallest representable value, then we know that the corresponding wrap type can not occur. Differential Revision: https://reviews.llvm.org/D108601 --- llvm/lib/Analysis/ScalarEvolution.cpp | 13 +++++++++++++ llvm/test/Analysis/ScalarEvolution/ptrtoint.ll | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index b43e69f..069a358 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -2390,6 +2390,19 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type, } } + // <0,+,nonnegative> is also nuw + // is also nsw + if (Type == scAddRecExpr && ScalarEvolution::hasFlags(Flags, SCEV::FlagNW) && + Ops.size() == 2) { + if (!ScalarEvolution::hasFlags(Flags, SCEV::FlagNUW) && Ops[0]->isZero() && + IsKnownNonNegative(Ops[1])) + Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW); + if (!ScalarEvolution::hasFlags(Flags, SCEV::FlagNSW) && + isa(Ops[0]) && + cast(Ops[0])->getAPInt().isMinSignedValue()) + Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW); + } + return Flags; } diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll index f4e7164..f09588b 100644 --- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll +++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll @@ -386,7 +386,7 @@ define void @pr46786_c26_char(i8* %arg, i8* %arg1, i8* %arg2) { ; X64-NEXT: %i9 = ptrtoint i8* %i7 to i64 ; X64-NEXT: --> {(ptrtoint i8* %arg to i64),+,1}<%bb6> U: full-set S: full-set Exits: (-1 + (ptrtoint i8* %arg1 to i64)) LoopDispositions: { %bb6: Computable } ; X64-NEXT: %i10 = sub i64 %i9, %i4 -; X64-NEXT: --> {0,+,1}<%bb6> U: full-set S: full-set Exits: (-1 + (-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* %arg1 to i64)) LoopDispositions: { %bb6: Computable } +; X64-NEXT: --> {0,+,1}<%bb6> U: full-set S: full-set Exits: (-1 + (-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* %arg1 to i64)) LoopDispositions: { %bb6: Computable } ; X64-NEXT: %i11 = getelementptr inbounds i8, i8* %arg2, i64 %i10 ; X64-NEXT: --> {%arg2,+,1}<%bb6> U: full-set S: full-set Exits: (-1 + (-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* %arg1 to i64) + %arg2) LoopDispositions: { %bb6: Computable } ; X64-NEXT: %i12 = load i8, i8* %i11, align 1 @@ -413,7 +413,7 @@ define void @pr46786_c26_char(i8* %arg, i8* %arg1, i8* %arg2) { ; X32-NEXT: %i9 = ptrtoint i8* %i7 to i64 ; X32-NEXT: --> {(zext i32 (ptrtoint i8* %arg to i32) to i64),+,1}<%bb6> U: [0,8589934591) S: [0,8589934591) Exits: ((zext i32 (-1 + (-1 * (ptrtoint i8* %arg to i32)) + (ptrtoint i8* %arg1 to i32)) to i64) + (zext i32 (ptrtoint i8* %arg to i32) to i64)) LoopDispositions: { %bb6: Computable } ; X32-NEXT: %i10 = sub i64 %i9, %i4 -; X32-NEXT: --> {0,+,1}<%bb6> U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 (-1 + (-1 * (ptrtoint i8* %arg to i32)) + (ptrtoint i8* %arg1 to i32)) to i64) LoopDispositions: { %bb6: Computable } +; X32-NEXT: --> {0,+,1}<%bb6> U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 (-1 + (-1 * (ptrtoint i8* %arg to i32)) + (ptrtoint i8* %arg1 to i32)) to i64) LoopDispositions: { %bb6: Computable } ; X32-NEXT: %i11 = getelementptr inbounds i8, i8* %arg2, i64 %i10 ; X32-NEXT: --> {%arg2,+,1}<%bb6> U: full-set S: full-set Exits: (-1 + (-1 * (ptrtoint i8* %arg to i32)) + (ptrtoint i8* %arg1 to i32) + %arg2) LoopDispositions: { %bb6: Computable } ; X32-NEXT: %i12 = load i8, i8* %i11, align 1 @@ -471,7 +471,7 @@ define void @pr46786_c26_int(i32* %arg, i32* %arg1, i32* %arg2) { ; X64-NEXT: %i9 = ptrtoint i32* %i7 to i64 ; X64-NEXT: --> {(ptrtoint i32* %arg to i64),+,4}<%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* %arg1 to i64)) /u 4)) + (ptrtoint i32* %arg to i64)) LoopDispositions: { %bb6: Computable } ; X64-NEXT: %i10 = sub i64 %i9, %i4 -; X64-NEXT: --> {0,+,4}<%bb6> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* %arg1 to i64)) /u 4)) LoopDispositions: { %bb6: Computable } +; X64-NEXT: --> {0,+,4}<%bb6> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* %arg1 to i64)) /u 4)) LoopDispositions: { %bb6: Computable } ; X64-NEXT: %i11 = ashr exact i64 %i10, 2 ; X64-NEXT: --> %i11 U: [-2305843009213693952,2305843009213693952) S: [-2305843009213693952,2305843009213693952) Exits: <> LoopDispositions: { %bb6: Variant } ; X64-NEXT: %i12 = getelementptr inbounds i32, i32* %arg2, i64 %i11 @@ -500,7 +500,7 @@ define void @pr46786_c26_int(i32* %arg, i32* %arg1, i32* %arg2) { ; X32-NEXT: %i9 = ptrtoint i32* %i7 to i64 ; X32-NEXT: --> {(zext i32 (ptrtoint i32* %arg to i32) to i64),+,4}<%bb6> U: [0,8589934588) S: [0,8589934588) Exits: ((zext i32 (ptrtoint i32* %arg to i32) to i64) + (4 * ((zext i32 (-4 + (-1 * (ptrtoint i32* %arg to i32)) + (ptrtoint i32* %arg1 to i32)) to i64) /u 4))) LoopDispositions: { %bb6: Computable } ; X32-NEXT: %i10 = sub i64 %i9, %i4 -; X32-NEXT: --> {0,+,4}<%bb6> U: [0,4294967293) S: [0,4294967293) Exits: (4 * ((zext i32 (-4 + (-1 * (ptrtoint i32* %arg to i32)) + (ptrtoint i32* %arg1 to i32)) to i64) /u 4)) LoopDispositions: { %bb6: Computable } +; X32-NEXT: --> {0,+,4}<%bb6> U: [0,4294967293) S: [0,4294967293) Exits: (4 * ((zext i32 (-4 + (-1 * (ptrtoint i32* %arg to i32)) + (ptrtoint i32* %arg1 to i32)) to i64) /u 4)) LoopDispositions: { %bb6: Computable } ; X32-NEXT: %i11 = ashr exact i64 %i10, 2 ; X32-NEXT: --> %i11 U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: <> LoopDispositions: { %bb6: Variant } ; X32-NEXT: %i12 = getelementptr inbounds i32, i32* %arg2, i64 %i11 -- 2.7.4