-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SCCP] Infer nuw for gep nusw with non-negative offsets #118819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-function-specialization Author: Nikita Popov (nikic) ChangesIf the GEP is nusw/inbounds and has all-non-negative offsets infer nuw as well. This doesn't have measurable compile-time impact. Proof: https://alive2.llvm.org/ce/z/ihztLy Full diff: https://github.com/llvm/llvm-project/pull/118819.diff 5 Files Affected:
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 4225e7e80fda6f..81aa7ce1cfe660 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -147,6 +147,16 @@ static bool refineInstruction(SCCPSolver &Solver,
Changed = true;
}
}
+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst)) {
+ if (GEP->hasNoUnsignedWrap() || !GEP->hasNoUnsignedSignedWrap())
+ return false;
+
+ if (all_of(GEP->indices(),
+ [&](Value *V) { return GetRange(V).isAllNonNegative(); })) {
+ GEP->setNoWrapFlags(GEP->getNoWrapFlags() |
+ GEPNoWrapFlags::noUnsignedWrap());
+ Changed = true;
+ }
}
return Changed;
diff --git a/llvm/test/Transforms/SCCP/conditions-iter-order.ll b/llvm/test/Transforms/SCCP/conditions-iter-order.ll
index c7f977b8ab83ae..1e8ba6197ad5f4 100644
--- a/llvm/test/Transforms/SCCP/conditions-iter-order.ll
+++ b/llvm/test/Transforms/SCCP/conditions-iter-order.ll
@@ -13,17 +13,17 @@ define internal ptr @spam(ptr %arg) {
; CHECK-NEXT: [[TMP:%.*]] = call ptr @malloc(i64 10368)
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARG:%.*]], align 8
; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], 1
-; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i32 1
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw i32, ptr [[ARG]], i32 1
; CHECK-NEXT: [[TMP10:%.*]] = icmp ne ptr [[TMP7]], null
; CHECK-NEXT: br i1 [[TMP10]], label [[BB17:%.*]], label [[BB13:%.*]]
; CHECK: bb13:
-; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i32 2
+; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw i32, ptr [[ARG]], i32 2
; CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 8
; CHECK-NEXT: [[TMP16:%.*]] = add i32 [[TMP15]], 1
; CHECK-NEXT: br label [[BB30:%.*]]
; CHECK: bb17:
; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i32 [[TMP6]], [[TMP5]]
-; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i32 3
+; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw i32, ptr [[ARG]], i32 3
; CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 8
; CHECK-NEXT: br i1 [[TMP18]], label [[BB30]], label [[BB13]]
; CHECK: bb30:
diff --git a/llvm/test/Transforms/SCCP/gep-nuw.ll b/llvm/test/Transforms/SCCP/gep-nuw.ll
index 298c14adc92a45..4d25642eb85750 100644
--- a/llvm/test/Transforms/SCCP/gep-nuw.ll
+++ b/llvm/test/Transforms/SCCP/gep-nuw.ll
@@ -6,7 +6,7 @@ define ptr @gep_nusw_nneg(ptr %p, i32 %x, i32 %y) {
; CHECK-SAME: ptr [[P:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X]] to i64
; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y]] to i64
-; CHECK-NEXT: [[GEP:%.*]] = getelementptr nusw [1 x i8], ptr [[P]], i64 [[X_EXT]], i64 [[Y_EXT]]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr nusw nuw [1 x i8], ptr [[P]], i64 [[X_EXT]], i64 [[Y_EXT]]
; CHECK-NEXT: ret ptr [[GEP]]
;
%x.ext = zext i32 %x to i64
@@ -20,7 +20,7 @@ define ptr @gep_inbounds_nneg(ptr %p, i32 %x, i32 %y) {
; CHECK-SAME: ptr [[P:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X]] to i64
; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y]] to i64
-; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [1 x i8], ptr [[P]], i64 [[X_EXT]], i64 [[Y_EXT]]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw [1 x i8], ptr [[P]], i64 [[X_EXT]], i64 [[Y_EXT]]
; CHECK-NEXT: ret ptr [[GEP]]
;
%x.ext = zext i32 %x to i64
diff --git a/llvm/test/Transforms/SCCP/ipsccp-ssa-copy-nested-conds.ll b/llvm/test/Transforms/SCCP/ipsccp-ssa-copy-nested-conds.ll
index 55a7fdf7197e5a..752e5038033106 100644
--- a/llvm/test/Transforms/SCCP/ipsccp-ssa-copy-nested-conds.ll
+++ b/llvm/test/Transforms/SCCP/ipsccp-ssa-copy-nested-conds.ll
@@ -15,11 +15,11 @@ define i32 @check(ptr %node) {
; CHECK: if.end:
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[NODE]], align 8
; CHECK-NEXT: [[CALL:%.*]] = call i32 @check(ptr [[TMP0]])
-; CHECK-NEXT: [[RIGHT:%.*]] = getelementptr inbounds [[STRUCT_NODE:%.*]], ptr [[NODE]], i32 0, i32 1
+; CHECK-NEXT: [[RIGHT:%.*]] = getelementptr inbounds nuw [[STRUCT_NODE:%.*]], ptr [[NODE]], i32 0, i32 1
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[RIGHT]], align 8
; CHECK-NEXT: [[CALL1:%.*]] = call i32 @check(ptr [[TMP1]])
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[RIGHT]], align 8
-; CHECK-NEXT: [[HEIGHT:%.*]] = getelementptr inbounds [[STRUCT_NODE]], ptr [[TMP2]], i32 0, i32 2
+; CHECK-NEXT: [[HEIGHT:%.*]] = getelementptr inbounds nuw [[STRUCT_NODE]], ptr [[TMP2]], i32 0, i32 2
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[HEIGHT]], align 4
; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[TMP3]], [[CALL1]]
; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]]
diff --git a/llvm/test/Transforms/SCCP/widening.ll b/llvm/test/Transforms/SCCP/widening.ll
index 144c3fd54e75b6..8c661bee8f5990 100644
--- a/llvm/test/Transforms/SCCP/widening.ll
+++ b/llvm/test/Transforms/SCCP/widening.ll
@@ -566,7 +566,7 @@ declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias
define linkonce_odr dereferenceable(1) ptr @spam(ptr %arg, i32 %arg1) align 2 {
; SCCP-LABEL: @spam(
; SCCP-NEXT: bb:
-; SCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], ptr [[ARG:%.*]], i32 0, i32 3
+; SCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds nuw [[STRUCT_BAZ_1:%.*]], ptr [[ARG:%.*]], i32 0, i32 3
; SCCP-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8
; SCCP-NEXT: [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64
; SCCP-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 [[TMP3]]
@@ -574,7 +574,7 @@ define linkonce_odr dereferenceable(1) ptr @spam(ptr %arg, i32 %arg1) align 2 {
;
; IPSCCP-LABEL: @spam(
; IPSCCP-NEXT: bb:
-; IPSCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], ptr [[ARG:%.*]], i32 0, i32 3
+; IPSCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds nuw [[STRUCT_BAZ_1:%.*]], ptr [[ARG:%.*]], i32 0, i32 3
; IPSCCP-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8
; IPSCCP-NEXT: [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64
; IPSCCP-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 [[TMP3]]
@@ -595,7 +595,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
; SCCP-NEXT: [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]]
; SCCP-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 65535
; SCCP-NEXT: [[TMP4:%.*]] = mul i32 [[ARG1]], 8
-; SCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], ptr [[ARG:%.*]], i32 0, i32 1
+; SCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT_BLAM_2:%.*]], ptr [[ARG:%.*]], i32 0, i32 1
; SCCP-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 8
; SCCP-NEXT: [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]]
; SCCP-NEXT: br label [[BB8:%.*]]
@@ -609,7 +609,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
; SCCP-NEXT: [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]]
; SCCP-NEXT: [[TMP16:%.*]] = mul i32 [[TMP15]], 4
; SCCP-NEXT: [[TMP17]] = call dereferenceable(1) ptr @spam(ptr [[ARG]], i32 [[TMP16]])
-; SCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 2
+; SCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP17]], i64 2
; SCCP-NEXT: [[TMP20:%.*]] = load i8, ptr [[TMP19]], align 1
; SCCP-NEXT: [[TMP21:%.*]] = zext i8 [[TMP20]] to i32
; SCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
@@ -632,7 +632,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
; SCCP-NEXT: [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0
; SCCP-NEXT: br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]]
; SCCP: bb35:
-; SCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds i8, ptr [[TMP32]], i64 1
+; SCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP32]], i64 1
; SCCP-NEXT: br label [[BB66:%.*]]
; SCCP: bb37:
; SCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8
@@ -677,7 +677,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
; IPSCCP-NEXT: [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]]
; IPSCCP-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 65535
; IPSCCP-NEXT: [[TMP4:%.*]] = mul i32 [[ARG1]], 8
-; IPSCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], ptr [[ARG:%.*]], i32 0, i32 1
+; IPSCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT_BLAM_2:%.*]], ptr [[ARG:%.*]], i32 0, i32 1
; IPSCCP-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 8
; IPSCCP-NEXT: [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]]
; IPSCCP-NEXT: br label [[BB8:%.*]]
@@ -691,7 +691,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
; IPSCCP-NEXT: [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]]
; IPSCCP-NEXT: [[TMP16:%.*]] = mul i32 [[TMP15]], 4
; IPSCCP-NEXT: [[TMP17]] = call dereferenceable(1) ptr @spam(ptr [[ARG]], i32 [[TMP16]])
-; IPSCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 2
+; IPSCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP17]], i64 2
; IPSCCP-NEXT: [[TMP20:%.*]] = load i8, ptr [[TMP19]], align 1
; IPSCCP-NEXT: [[TMP21:%.*]] = zext i8 [[TMP20]] to i32
; IPSCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
@@ -714,7 +714,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
; IPSCCP-NEXT: [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0
; IPSCCP-NEXT: br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]]
; IPSCCP: bb35:
-; IPSCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds i8, ptr [[TMP32]], i64 1
+; IPSCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP32]], i64 1
; IPSCCP-NEXT: br label [[BB66:%.*]]
; IPSCCP: bb37:
; IPSCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8
|
If the GEP is nusw/inbounds and has all-non-negative offsets infer nuw as well. Proof: https://alive2.llvm.org/ce/z/ihztLy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
If the GEP is nusw/inbounds and has all-non-negative offsets infer nuw as well.
This doesn't have measurable compile-time impact.
Proof: https://alive2.llvm.org/ce/z/ihztLy