[llvm] 4a7abfe - [InstCombine] Preserve nuw in OptimizePointerDifference

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 4 07:58:47 PST 2024


Author: Nikita Popov
Date: 2024-12-04T16:58:35+01:00
New Revision: 4a7abfe0a7b9b43cc60115caab810f4c24e53f1c

URL: https://github.com/llvm/llvm-project/commit/4a7abfe0a7b9b43cc60115caab810f4c24e53f1c
DIFF: https://github.com/llvm/llvm-project/commit/4a7abfe0a7b9b43cc60115caab810f4c24e53f1c.diff

LOG: [InstCombine] Preserve nuw in OptimizePointerDifference

If both the geps and the subs are nuw the new sub is also nuw.

Proof: https://alive2.llvm.org/ce/z/mM8UvF

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/test/Transforms/InstCombine/sub-gep.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 63725e4ca8113e..b9f847d4d66406 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2109,11 +2109,13 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
 
   // If we have a 2nd GEP of the same base pointer, subtract the offsets.
   // If both GEPs are inbounds, then the subtract does not have signed overflow.
+  // If both GEPs are nuw and the original sub is nuw, the new sub is also nuw.
   if (GEP2) {
-    bool GEP2IsInBounds = GEP2->isInBounds();
     Value *Offset = EmitGEPOffset(GEP2, RewriteGEPs);
-    Result = Builder.CreateSub(Result, Offset, "gep
diff ", /* NUW */ false,
-                               GEP1IsInBounds && GEP2IsInBounds);
+    Result = Builder.CreateSub(Result, Offset, "gep
diff ",
+                               IsNUW && GEP1->hasNoUnsignedWrap() &&
+                                   GEP2->hasNoUnsignedWrap(),
+                               GEP1IsInBounds && GEP2->isInBounds());
   }
 
   // If we have p - gep(p, ...)  then we have to negate the result.

diff  --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index f7a54ab2141bd7..5f336b49323ec0 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -156,6 +156,62 @@ define i64 @test_inbounds_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
   ret i64 %d
 }
 
+define i64 @test_nusw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
+; CHECK-LABEL: @test_nusw_two_gep(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
+; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
+; CHECK-NEXT:    ret i64 [[GEPDIFF]]
+;
+  %p1 = getelementptr nusw [0 x i32], ptr %base, i64 0, i64 %idx
+  %p2 = getelementptr nusw [0 x i32], ptr %base, i64 0, i64 %idx2
+  %i1 = ptrtoint ptr %p1 to i64
+  %i2 = ptrtoint ptr %p2 to i64
+  %d = sub i64 %i2, %i1
+  ret i64 %d
+}
+
+define i64 @test_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
+; CHECK-LABEL: @test_nuw_two_gep(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub nuw i64 [[IDX2:%.*]], [[IDX:%.*]]
+; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nuw i64 [[TMP1]], 2
+; CHECK-NEXT:    ret i64 [[GEPDIFF]]
+;
+  %p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
+  %p2 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx2
+  %i1 = ptrtoint ptr %p1 to i64
+  %i2 = ptrtoint ptr %p2 to i64
+  %d = sub nuw i64 %i2, %i1
+  ret i64 %d
+}
+
+define i64 @test_nuw_two_gep_missing_nuw_on_sub(ptr %base, i64 %idx, i64 %idx2) {
+; CHECK-LABEL: @test_nuw_two_gep_missing_nuw_on_sub(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
+; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
+; CHECK-NEXT:    ret i64 [[GEPDIFF]]
+;
+  %p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
+  %p2 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx2
+  %i1 = ptrtoint ptr %p1 to i64
+  %i2 = ptrtoint ptr %p2 to i64
+  %d = sub i64 %i2, %i1
+  ret i64 %d
+}
+
+define i64 @test_nuw_two_gep_missing_nuw_on_one_gep(ptr %base, i64 %idx, i64 %idx2) {
+; CHECK-LABEL: @test_nuw_two_gep_missing_nuw_on_one_gep(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
+; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
+; CHECK-NEXT:    ret i64 [[GEPDIFF]]
+;
+  %p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
+  %p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx2
+  %i1 = ptrtoint ptr %p1 to i64
+  %i2 = ptrtoint ptr %p2 to i64
+  %d = sub nuw i64 %i2, %i1
+  ret i64 %d
+}
+
 define i64 @test_inbounds_nuw_multi_index(ptr %base, i64 %idx, i64 %idx2) {
 ; CHECK-LABEL: @test_inbounds_nuw_multi_index(
 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 3


        


More information about the llvm-commits mailing list