[llvm] b14be1e - [SCEV] Use object size for globals to sharpen ranges.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 29 13:33:51 PDT 2023
Author: Florian Hahn
Date: 2023-04-29T21:33:30+01:00
New Revision: b14be1e7c0530c3c82e965104f160a4b357f91ed
URL: https://github.com/llvm/llvm-project/commit/b14be1e7c0530c3c82e965104f160a4b357f91ed
DIFF: https://github.com/llvm/llvm-project/commit/b14be1e7c0530c3c82e965104f160a4b357f91ed.diff
LOG: [SCEV] Use object size for globals to sharpen ranges.
The highest address the object can start is ObjSize bytes before the
end (unsigned max value). If this value is not a multiple of the
alignment, the last possible start value is the next lowest multiple
of the alignment. Note: The computations cannot overflow,
because if they would there's no possible start address for the
object.
At the moment, this is limited to GlobalVariables, because I could not
find a API similar to getObjectSize to also get the alignment of the
object. With such an API, this can be generalized to general addresses.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D149483
Added:
Modified:
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
llvm/test/Analysis/ScalarEvolution/load.ll
llvm/test/Analysis/ScalarEvolution/ptrtoint-global.ll
llvm/test/Transforms/IndVarSimplify/ptrtoint-global-cmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 641bf7b7f8d17..306090f3eb11c 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -76,6 +76,7 @@
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -6773,6 +6774,31 @@ const ConstantRange &ScalarEvolution::getRangeRef(
APInt::getSignedMaxValue(BitWidth).ashr(NS - 1) + 1),
RangeType);
+ if (U->getType()->isPointerTy() && SignHint == HINT_RANGE_UNSIGNED) {
+ // Strengthen the range if the underlying IR value is a global using the
+ // size of the global.
+ ObjectSizeOpts Opts;
+ Opts.RoundToAlign = false;
+ Opts.NullIsUnknownSize = true;
+ uint64_t ObjSize;
+ auto *GV = dyn_cast<GlobalVariable>(U->getValue());
+ if (GV && getObjectSize(U->getValue(), ObjSize, DL, &TLI, Opts) &&
+ ObjSize > 1) {
+ // The highest address the object can start is ObjSize bytes before the
+ // end (unsigned max value). If this value is not a multiple of the
+ // alignment, the last possible start value is the next lowest multiple
+ // of the alignment. Note: The computations below cannot overflow,
+ // because if they would there's no possible start address for the
+ // object.
+ APInt MaxVal = APInt::getMaxValue(BitWidth) - APInt(BitWidth, ObjSize);
+ uint64_t Align = GV->getAlign().valueOrOne().value();
+ uint64_t Rem = MaxVal.urem(Align);
+ MaxVal -= APInt(BitWidth, Rem);
+ ConservativeResult = ConservativeResult.intersectWith(
+ {ConservativeResult.getUnsignedMin(), MaxVal + 1}, RangeType);
+ }
+ }
+
// A range of Phi is a subset of union of all ranges of its input.
if (PHINode *Phi = dyn_cast<PHINode>(U->getValue())) {
// Make sure that we do not run over cycled Phis.
diff --git a/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll b/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
index 98b832dedacea..825b4abb5e8c5 100644
--- a/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
+++ b/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
@@ -21,7 +21,7 @@ define dso_local i32 @f() {
; CHECK-NEXT: %idxprom20 = zext i32 %storemerge1921 to i64
; CHECK-NEXT: --> (zext i32 {3,+,-1}<nsw><%for.cond6> to i64) U: [3,4) S: [3,4) Exits: <<Unknown>> LoopDispositions: { %for.cond6: Computable, %outer.loop: Variant }
; CHECK-NEXT: %arrayidx7 = getelementptr inbounds [1 x [4 x i16]], ptr @__const.f.g, i64 0, i64 0, i64 %idxprom20
-; CHECK-NEXT: --> ((2 * (zext i32 {3,+,-1}<nsw><%for.cond6> to i64))<nuw><nsw> + @__const.f.g)<nuw> U: [6,-1) S: [-9223372036854775808,9223372036854775807) Exits: <<Unknown>> LoopDispositions: { %for.cond6: Computable, %outer.loop: Variant }
+; CHECK-NEXT: --> ((2 * (zext i32 {3,+,-1}<nsw><%for.cond6> to i64))<nuw><nsw> + @__const.f.g)<nuw> U: [6,-3) S: [-9223372036854775808,9223372036854775807) Exits: <<Unknown>> LoopDispositions: { %for.cond6: Computable, %outer.loop: Variant }
; CHECK-NEXT: %i = load i16, ptr %arrayidx7, align 2
; CHECK-NEXT: --> %i U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond6: Variant, %outer.loop: Variant }
; CHECK-NEXT: %storemerge1822.lcssa.ph = phi i32 [ 0, %for.cond6 ]
@@ -45,7 +45,7 @@ define dso_local i32 @f() {
; CHECK-NEXT: %idxprom20.3 = zext i32 %storemerge1921.3 to i64
; CHECK-NEXT: --> (zext i32 {3,+,-1}<nsw><%inner.loop> to i64) U: [3,4) S: [3,4) Exits: <<Unknown>> LoopDispositions: { %inner.loop: Computable, %outer.loop: Variant }
; CHECK-NEXT: %arrayidx7.3 = getelementptr inbounds [1 x [4 x i16]], ptr @__const.f.g, i64 0, i64 0, i64 %idxprom20.3
-; CHECK-NEXT: --> ((2 * (zext i32 {3,+,-1}<nsw><%inner.loop> to i64))<nuw><nsw> + @__const.f.g)<nuw> U: [6,-1) S: [-9223372036854775808,9223372036854775807) Exits: <<Unknown>> LoopDispositions: { %inner.loop: Computable, %outer.loop: Variant }
+; CHECK-NEXT: --> ((2 * (zext i32 {3,+,-1}<nsw><%inner.loop> to i64))<nuw><nsw> + @__const.f.g)<nuw> U: [6,-3) S: [-9223372036854775808,9223372036854775807) Exits: <<Unknown>> LoopDispositions: { %inner.loop: Computable, %outer.loop: Variant }
; CHECK-NEXT: %i7 = load i16, ptr %arrayidx7.3, align 2
; CHECK-NEXT: --> %i7 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %inner.loop: Variant, %outer.loop: Variant }
; CHECK-NEXT: %i8 = load volatile i32, ptr @b, align 4
diff --git a/llvm/test/Analysis/ScalarEvolution/load.ll b/llvm/test/Analysis/ScalarEvolution/load.ll
index 5ba3dff9d9df1..b95ad89f2def9 100644
--- a/llvm/test/Analysis/ScalarEvolution/load.ll
+++ b/llvm/test/Analysis/ScalarEvolution/load.ll
@@ -16,11 +16,11 @@ define i32 @test1() nounwind readnone {
; CHECK-NEXT: %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> U: [0,50) S: [0,50) Exits: 49 LoopDispositions: { %for.body: Computable }
; CHECK-NEXT: %arrayidx = getelementptr inbounds [50 x i32], ptr @arr1, i32 0, i32 %i.03
-; CHECK-NEXT: --> {@arr1,+,4}<nuw><%for.body> U: [0,-3) S: [-2147483648,2147483645) Exits: (196 + @arr1) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT: --> {@arr1,+,4}<nuw><%for.body> U: [0,-7) S: [-2147483648,2147483645) Exits: (196 + @arr1)<nuw> LoopDispositions: { %for.body: Computable }
; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4
; CHECK-NEXT: --> %0 U: full-set S: full-set Exits: 50 LoopDispositions: { %for.body: Variant }
; CHECK-NEXT: %arrayidx1 = getelementptr inbounds [50 x i32], ptr @arr2, i32 0, i32 %i.03
-; CHECK-NEXT: --> {@arr2,+,4}<nuw><%for.body> U: [0,-3) S: [-2147483648,2147483645) Exits: (196 + @arr2) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT: --> {@arr2,+,4}<nuw><%for.body> U: [0,-7) S: [-2147483648,2147483645) Exits: (196 + @arr2)<nuw> LoopDispositions: { %for.body: Computable }
; CHECK-NEXT: %1 = load i32, ptr %arrayidx1, align 4
; CHECK-NEXT: --> %1 U: full-set S: full-set Exits: 0 LoopDispositions: { %for.body: Variant }
; CHECK-NEXT: %add = add i32 %0, %sum.04
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint-global.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint-global.ll
index a76acbb77ac7b..dc73e28db9527 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint-global.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint-global.ll
@@ -10,7 +10,7 @@ define i64 @ptrtoint_align_2_size_4_add_5() {
; CHECK-LABEL: 'ptrtoint_align_2_size_4_add_5'
; CHECK-NEXT: Classifying expressions for: @ptrtoint_align_2_size_4_add_5
; CHECK-NEXT: %add = add i64 ptrtoint (ptr @glob.i32.align2 to i64), 5
-; CHECK-NEXT: --> (5 + (ptrtoint ptr @glob.i32.align2 to i64)) U: [5,4) S: [-9223372036854775803,-9223372036854775804)
+; CHECK-NEXT: --> (5 + (ptrtoint ptr @glob.i32.align2 to i64))<nuw> U: [5,0) S: [5,0)
; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_align_2_size_4_add_5
;
entry:
@@ -82,7 +82,7 @@ define i64 @ptrtoint_align_16_size_16_add_16() {
; CHECK-LABEL: 'ptrtoint_align_16_size_16_add_16'
; CHECK-NEXT: Classifying expressions for: @ptrtoint_align_16_size_16_add_16
; CHECK-NEXT: %add = add i64 ptrtoint (ptr @array4xi32 to i64), 16
-; CHECK-NEXT: --> (16 + (ptrtoint ptr @array4xi32 to i64)) U: [0,-15) S: [-9223372036854775808,9223372036854775793)
+; CHECK-NEXT: --> (16 + (ptrtoint ptr @array4xi32 to i64))<nuw> U: [16,-15) S: [-9223372036854775808,9223372036854775793)
; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_align_16_size_16_add_16
;
entry:
@@ -94,7 +94,7 @@ define i64 @ptrtoint_align_16_size_16_add_31() {
; CHECK-LABEL: 'ptrtoint_align_16_size_16_add_31'
; CHECK-NEXT: Classifying expressions for: @ptrtoint_align_16_size_16_add_31
; CHECK-NEXT: %add = add i64 ptrtoint (ptr @array4xi32 to i64), 31
-; CHECK-NEXT: --> (31 + (ptrtoint ptr @array4xi32 to i64)) U: [31,16) S: [-9223372036854775777,-9223372036854775792)
+; CHECK-NEXT: --> (31 + (ptrtoint ptr @array4xi32 to i64))<nuw> U: [31,0) S: [31,0)
; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_align_16_size_16_add_31
;
entry:
@@ -118,7 +118,7 @@ define i64 @ptrtoint_align_16_size_16_add_33() {
; CHECK-LABEL: 'ptrtoint_align_16_size_16_add_33'
; CHECK-NEXT: Classifying expressions for: @ptrtoint_align_16_size_16_add_33
; CHECK-NEXT: %add = add i64 ptrtoint (ptr @array4xi32 to i64), 33
-; CHECK-NEXT: --> (33 + (ptrtoint ptr @array4xi32 to i64)) U: [33,18) S: [-9223372036854775775,-9223372036854775790)
+; CHECK-NEXT: --> (33 + (ptrtoint ptr @array4xi32 to i64)) U: [33,2) S: [-9223372036854775775,-9223372036854775790)
; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_align_16_size_16_add_33
;
entry:
@@ -130,13 +130,13 @@ define i64 @ptrtoint_align_16_size_16_add_16_umax_sub() {
; CHECK-LABEL: 'ptrtoint_align_16_size_16_add_16_umax_sub'
; CHECK-NEXT: Classifying expressions for: @ptrtoint_align_16_size_16_add_16_umax_sub
; CHECK-NEXT: %add.16 = add i64 ptrtoint (ptr @array4xi32 to i64), 16
-; CHECK-NEXT: --> (16 + (ptrtoint ptr @array4xi32 to i64)) U: [0,-15) S: [-9223372036854775808,9223372036854775793)
+; CHECK-NEXT: --> (16 + (ptrtoint ptr @array4xi32 to i64))<nuw> U: [16,-15) S: [-9223372036854775808,9223372036854775793)
; CHECK-NEXT: %umax = call i64 @llvm.umax.i64(i64 ptrtoint (ptr @array4xi32 to i64), i64 %add.16)
-; CHECK-NEXT: --> ((16 + (ptrtoint ptr @array4xi32 to i64)) umax (ptrtoint ptr @array4xi32 to i64)) U: [0,-15) S: [-9223372036854775808,9223372036854775793)
+; CHECK-NEXT: --> (16 + (ptrtoint ptr @array4xi32 to i64))<nuw> U: [16,-15) S: [-9223372036854775808,9223372036854775793)
; CHECK-NEXT: %add = add i64 %umax, 16
-; CHECK-NEXT: --> (16 + ((16 + (ptrtoint ptr @array4xi32 to i64)) umax (ptrtoint ptr @array4xi32 to i64))) U: [0,-15) S: [-9223372036854775808,9223372036854775793)
+; CHECK-NEXT: --> (32 + (ptrtoint ptr @array4xi32 to i64)) U: [0,-15) S: [-9223372036854775808,9223372036854775793)
; CHECK-NEXT: %sub = sub i64 %add, ptrtoint (ptr @array4xi32 to i64)
-; CHECK-NEXT: --> (16 + (-1 * (ptrtoint ptr @array4xi32 to i64)) + ((16 + (ptrtoint ptr @array4xi32 to i64)) umax (ptrtoint ptr @array4xi32 to i64))) U: [0,-15) S: [-9223372036854775808,9223372036854775793)
+; CHECK-NEXT: --> 32 U: [32,33) S: [32,33)
; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_align_16_size_16_add_16_umax_sub
;
entry:
@@ -151,13 +151,13 @@ define i64 @ptrtoint_align_16_size_16_add_31_umax_sub() {
; CHECK-LABEL: 'ptrtoint_align_16_size_16_add_31_umax_sub'
; CHECK-NEXT: Classifying expressions for: @ptrtoint_align_16_size_16_add_31_umax_sub
; CHECK-NEXT: %add.31 = add i64 ptrtoint (ptr @array4xi32 to i64), 31
-; CHECK-NEXT: --> (31 + (ptrtoint ptr @array4xi32 to i64)) U: [31,16) S: [-9223372036854775777,-9223372036854775792)
+; CHECK-NEXT: --> (31 + (ptrtoint ptr @array4xi32 to i64))<nuw> U: [31,0) S: [31,0)
; CHECK-NEXT: %umax = call i64 @llvm.umax.i64(i64 ptrtoint (ptr @array4xi32 to i64), i64 %add.31)
-; CHECK-NEXT: --> ((31 + (ptrtoint ptr @array4xi32 to i64)) umax (ptrtoint ptr @array4xi32 to i64)) U: full-set S: full-set
+; CHECK-NEXT: --> (31 + (ptrtoint ptr @array4xi32 to i64))<nuw> U: [31,0) S: [31,0)
; CHECK-NEXT: %add = add i64 %umax, 16
-; CHECK-NEXT: --> (16 + ((31 + (ptrtoint ptr @array4xi32 to i64)) umax (ptrtoint ptr @array4xi32 to i64))) U: full-set S: full-set
+; CHECK-NEXT: --> (47 + (ptrtoint ptr @array4xi32 to i64)) U: [47,16) S: [-9223372036854775761,-9223372036854775776)
; CHECK-NEXT: %sub = sub i64 %add, ptrtoint (ptr @array4xi32 to i64)
-; CHECK-NEXT: --> (16 + (-1 * (ptrtoint ptr @array4xi32 to i64)) + ((31 + (ptrtoint ptr @array4xi32 to i64)) umax (ptrtoint ptr @array4xi32 to i64))) U: full-set S: full-set
+; CHECK-NEXT: --> 47 U: [47,48) S: [47,48)
; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_align_16_size_16_add_31_umax_sub
;
entry:
diff --git a/llvm/test/Transforms/IndVarSimplify/ptrtoint-global-cmp.ll b/llvm/test/Transforms/IndVarSimplify/ptrtoint-global-cmp.ll
index 4d43f2a7299e8..e06d83753fe29 100644
--- a/llvm/test/Transforms/IndVarSimplify/ptrtoint-global-cmp.ll
+++ b/llvm/test/Transforms/IndVarSimplify/ptrtoint-global-cmp.ll
@@ -6,25 +6,18 @@
define i32 @test() {
; CHECK-LABEL: define i32 @test() {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 ptrtoint (ptr @a to i64), i64 add (i64 ptrtoint (ptr @a to i64), i64 16))
-; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[UMAX]], 3
-; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], ptrtoint (ptr @a to i64)
-; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 2
-; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 4)
-; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[TMP2]], [[UMIN]]
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[RED:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP_LATCH]] ]
; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[IV]] to i64
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr @a, i64 [[IDXPROM]]
-; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
+; CHECK-NEXT: br i1 false, label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
; CHECK: loop.latch:
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4
; CHECK-NEXT: [[RED_NEXT]] = add nsw i32 [[L]], [[RED]]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV]], 4
-; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_HEADER]], label [[EXIT_2:%.*]]
+; CHECK-NEXT: br i1 true, label [[LOOP_HEADER]], label [[EXIT_2:%.*]]
; CHECK: exit.1:
; CHECK-NEXT: ret i32 0
; CHECK: exit.2:
More information about the llvm-commits
mailing list