[llvm] [InstCombine] fold `sub(zext(ptrtoint), zext(ptrtoint))` (PR #115369)

Nikolay Panchenko via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 14 17:12:03 PST 2024


https://github.com/npanchen updated https://github.com/llvm/llvm-project/pull/115369

>From e360e21ee174ac7fb59a3e6df1bb345eae5ed11e Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Thu, 7 Nov 2024 15:19:39 -0500
Subject: [PATCH 1/6] [InstCombine] fold `sub(zext(ptrtoint),zext(ptrtoint))`

On a 32-bit target if pointer arithmetic is used in i64 computation,
the missed folding in InstCombine results to suboptimal performance,
unlike same code compiled for 64bit target
---
 .../InstCombine/InstCombineAddSub.cpp         |  4 +-
 llvm/test/Transforms/InstCombine/sub-gep.ll   | 56 +++++++++++++++++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 21588aca512758..d931f89b9af421 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2618,8 +2618,8 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   // Optimize pointer differences into the same array into a size.  Consider:
   //  &A[10] - &A[0]: we should compile this to "10".
   Value *LHSOp, *RHSOp;
-  if (match(Op0, m_PtrToInt(m_Value(LHSOp))) &&
-      match(Op1, m_PtrToInt(m_Value(RHSOp))))
+  if (match(Op0, m_ZExtOrSelf(m_PtrToInt(m_Value(LHSOp)))) &&
+      match(Op1, m_ZExtOrSelf(m_PtrToInt(m_Value(RHSOp)))))
     if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType(),
                                                I.hasNoUnsignedWrap()))
       return replaceInstUsesWith(I, Res);
diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index b773d106b2c98a..ee18fd607823a5 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -270,6 +270,36 @@ define i64 @test25(ptr %P, i64 %A){
   ret i64 %G
 }
 
+define i64 @zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
+; CHECK-LABLE: @zext_ptrtoint_sub_ptrtoint(
+; CHECK-NEXT:  %1 = sext i32 %offset to i64
+; CHECK-NEXT:  %A = getelementptr bfloat, ptr @Arr, i64 %1
+; CHECK-NEXT:  %2 = ptrtoint ptr %A to i64
+; CHECK-NEXT:  %C = and i64 %2, 4294967294
+; CHECK-NEXT:  %D = sub i64 %C, ptrtoint (ptr @Arr to i64)
+; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr bfloat, ptr @Arr, i32 %offset
+  %B = ptrtoint ptr %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 %C, ptrtoint (ptr @Arr to i64)
+  ret i64 %D
+}
+
+define i64 @ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
+; CHECK-LABLE: @ptrtoint_sub_zext_ptrtoint(
+; CHECK-NEXT:  %1 = sext i32 %offset to i64
+; CHECK-NEXT:  %A = getelementptr bfloat, ptr @Arr, i64 %1
+; CHECK-NEXT:  %2 = ptrtoint ptr %A to i64
+; CHECK-NEXT:  %C = and i64 %2, 4294967294
+; CHECK-NEXT:  %D = sub i64 ptrtoint (ptr @Arr to i64), %C
+; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr bfloat, ptr @Arr, i32 %offset
+  %B = ptrtoint ptr %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 ptrtoint (ptr @Arr to i64), %C
+  ret i64 %D
+}
+
 @Arr_as1 = external addrspace(1) global [42 x i16]
 
 define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
@@ -285,6 +315,32 @@ define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
   ret i16 %G
 }
 
+define i64 @zext_ptrtoint_sub_ptrtoint_as1(ptr addrspace(1) %p, i32 %offset) {
+; CHECK-LABLE: @zext_ptrtoint_sub_ptrtoint_as1(
+; CHECK-NEXT:  %1 = trunc i32 %offset to i16
+; CHECK-NEXT:  %A.idx = shl i16 %1, 1
+; CHECK-NEXT:  %D = sext i16 %A.idx to i64
+; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr bfloat, ptr addrspace(1) @Arr_as1, i32 %offset
+  %B = ptrtoint ptr addrspace(1) %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 %C, ptrtoint (ptr addrspace(1) @Arr_as1 to i64)
+  ret i64 %D
+}
+
+define i64 @ptrtoint_sub_zext_ptrtoint_as1(ptr addrspace(1) %p, i32 %offset) {
+; CHECK-LABLE: @ptrtoint_sub_zext_ptrtoint_as1(
+; CHECK-NEXT:  %1 = trunc i32 %offset to i16
+; CHECK-NEXT:  %A.idx.neg = mul i16 %1, -2
+; CHECK-NEXT:  %D = sext i16 %A.idx.neg to i64
+; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr bfloat, ptr addrspace(1) @Arr_as1, i32 %offset
+  %B = ptrtoint ptr addrspace(1) %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 ptrtoint (ptr addrspace(1) @Arr_as1 to i64), %C
+  ret i64 %D
+}
+
 define i64 @test30(ptr %foo, i64 %i, i64 %j) {
 ; CHECK-LABEL: @test30(
 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2

>From 5c692fdb697e70ec7df72709910f6a5acd26cdd3 Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Fri, 8 Nov 2024 17:24:30 -0500
Subject: [PATCH 2/6] Changed pattern matching

---
 .../InstCombine/InstCombineAddSub.cpp         | 16 +++++++-
 llvm/test/Transforms/InstCombine/sub-gep.ll   | 39 ++++++++++---------
 2 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index d931f89b9af421..4f14b1eb57785c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2618,8 +2618,8 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   // Optimize pointer differences into the same array into a size.  Consider:
   //  &A[10] - &A[0]: we should compile this to "10".
   Value *LHSOp, *RHSOp;
-  if (match(Op0, m_ZExtOrSelf(m_PtrToInt(m_Value(LHSOp)))) &&
-      match(Op1, m_ZExtOrSelf(m_PtrToInt(m_Value(RHSOp)))))
+  if (match(Op0, m_PtrToInt(m_Value(LHSOp))) &&
+      match(Op1, m_PtrToInt(m_Value(RHSOp))))
     if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType(),
                                                I.hasNoUnsignedWrap()))
       return replaceInstUsesWith(I, Res);
@@ -2631,6 +2631,18 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
                                                /* IsNUW */ false))
       return replaceInstUsesWith(I, Res);
 
+  if (match(Op0, m_ZExt(m_PtrToInt(m_Value(LHSOp)))) &&
+      match(Op1, m_PtrToInt(m_Value(RHSOp))) && isa<GlobalValue>(RHSOp)) {
+    Value *Offset;
+    if (match(LHSOp, m_GEP(m_Specific(RHSOp), m_Value(Offset)))) {
+      auto *GEP = cast<GEPOperator>(LHSOp);
+      if (GEP->isInBounds()) {
+        Value *Res = Builder.CreateZExt(EmitGEPOffset(GEP), I.getType());
+        return replaceInstUsesWith(I, Res);
+      }
+    }
+  }
+
   // Canonicalize a shifty way to code absolute value to the common pattern.
   // There are 2 potential commuted variants.
   // We're relying on the fact that we only do this transform when the shift has
diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index ee18fd607823a5..e07539f4d20f32 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
 
-target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-p2:32:32"
 
 define i64 @test_inbounds(ptr %base, i64 %idx) {
 ; CHECK-LABEL: @test_inbounds(
@@ -271,7 +271,7 @@ define i64 @test25(ptr %P, i64 %A){
 }
 
 define i64 @zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
-; CHECK-LABLE: @zext_ptrtoint_sub_ptrtoint(
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint(
 ; CHECK-NEXT:  %1 = sext i32 %offset to i64
 ; CHECK-NEXT:  %A = getelementptr bfloat, ptr @Arr, i64 %1
 ; CHECK-NEXT:  %2 = ptrtoint ptr %A to i64
@@ -286,7 +286,7 @@ define i64 @zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
 }
 
 define i64 @ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
-; CHECK-LABLE: @ptrtoint_sub_zext_ptrtoint(
+; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint(
 ; CHECK-NEXT:  %1 = sext i32 %offset to i64
 ; CHECK-NEXT:  %A = getelementptr bfloat, ptr @Arr, i64 %1
 ; CHECK-NEXT:  %2 = ptrtoint ptr %A to i64
@@ -315,29 +315,30 @@ define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
   ret i16 %G
 }
 
-define i64 @zext_ptrtoint_sub_ptrtoint_as1(ptr addrspace(1) %p, i32 %offset) {
-; CHECK-LABLE: @zext_ptrtoint_sub_ptrtoint_as1(
-; CHECK-NEXT:  %1 = trunc i32 %offset to i16
-; CHECK-NEXT:  %A.idx = shl i16 %1, 1
-; CHECK-NEXT:  %D = sext i16 %A.idx to i64
+ at Arr_as2 = external addrspace(2) global [42 x i16]
+define i64 @zext_ptrtoint_sub_ptrtoint_as2(ptr addrspace(1) %p, i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2(
+; CHECK-NEXT:  %A.idx = shl nsw i32 %offset, 1
+; CHECK-NEXT:  %D = zext i32 %A.idx to i64
 ; CHECK-NEXT:  ret i64 %D
-  %A = getelementptr bfloat, ptr addrspace(1) @Arr_as1, i32 %offset
-  %B = ptrtoint ptr addrspace(1) %A to i32
+  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
-  %D = sub i64 %C, ptrtoint (ptr addrspace(1) @Arr_as1 to i64)
+  %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
   ret i64 %D
 }
 
-define i64 @ptrtoint_sub_zext_ptrtoint_as1(ptr addrspace(1) %p, i32 %offset) {
-; CHECK-LABLE: @ptrtoint_sub_zext_ptrtoint_as1(
-; CHECK-NEXT:  %1 = trunc i32 %offset to i16
-; CHECK-NEXT:  %A.idx.neg = mul i16 %1, -2
-; CHECK-NEXT:  %D = sext i16 %A.idx.neg to i64
+define i64 @ptrtoint_sub_zext_ptrtoint_as2(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2(
+; CHECK-NEXT:  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+; CHECK-NEXT:  %B = ptrtoint ptr addrspace(2) %A to i32
+; CHECK-NEXT:  %C = zext i32 %B to i64
+; CHECK-NEXT:  %D = sub nsw i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), %C
 ; CHECK-NEXT:  ret i64 %D
-  %A = getelementptr bfloat, ptr addrspace(1) @Arr_as1, i32 %offset
-  %B = ptrtoint ptr addrspace(1) %A to i32
+  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
-  %D = sub i64 ptrtoint (ptr addrspace(1) @Arr_as1 to i64), %C
+  %D = sub i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), %C
   ret i64 %D
 }
 

>From a2b3e0358f21c0dc97703023930bcb4dfc8aafd7 Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Wed, 13 Nov 2024 18:15:01 -0500
Subject: [PATCH 3/6] Addressed comments

---
 .../InstCombine/InstCombineAddSub.cpp         | 17 ++++---
 llvm/test/Transforms/InstCombine/sub-gep.ll   | 44 +++++++++++++++++--
 2 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 4f14b1eb57785c..40172bf2cd1eb7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2632,13 +2632,16 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
       return replaceInstUsesWith(I, Res);
 
   if (match(Op0, m_ZExt(m_PtrToInt(m_Value(LHSOp)))) &&
-      match(Op1, m_PtrToInt(m_Value(RHSOp))) && isa<GlobalValue>(RHSOp)) {
-    Value *Offset;
-    if (match(LHSOp, m_GEP(m_Specific(RHSOp), m_Value(Offset)))) {
-      auto *GEP = cast<GEPOperator>(LHSOp);
-      if (GEP->isInBounds()) {
-        Value *Res = Builder.CreateZExt(EmitGEPOffset(GEP), I.getType());
-        return replaceInstUsesWith(I, Res);
+      match(Op1, m_ZExtOrSelf(m_PtrToInt(m_Value(RHSOp))))) {
+    if (auto *GEP = dyn_cast<GEPOperator>(LHSOp)) {
+      if (GEP->getPointerOperand() == RHSOp) {
+        if (GEP->hasNoUnsignedWrap() || GEP->hasNoUnsignedSignedWrap()) {
+          Value *Offset = EmitGEPOffset(GEP);
+          Value *Res = GEP->hasNoUnsignedWrap()
+                           ? Builder.CreateZExt(Offset, I.getType())
+                           : Builder.CreateSExt(Offset, I.getType());
+          return replaceInstUsesWith(I, Res);
+        }
       }
     }
   }
diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index e07539f4d20f32..3a566b4193116a 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -316,19 +316,57 @@ define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
 }
 
 @Arr_as2 = external addrspace(2) global [42 x i16]
-define i64 @zext_ptrtoint_sub_ptrtoint_as2(ptr addrspace(1) %p, i32 %offset) {
+define i64 @zext_ptrtoint_sub_ptrtoint_as2(i32 %offset) {
 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2(
 ; CHECK-NEXT:  %A.idx = shl nsw i32 %offset, 1
+; CHECK-NEXT:  %D = sext i32 %A.idx to i64
+; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr nusw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
+  ret i64 %D
+}
+
+define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nuw(
+; CHECK-NEXT:  %A.idx = shl nuw i32 %offset, 1
 ; CHECK-NEXT:  %D = zext i32 %A.idx to i64
 ; CHECK-NEXT:  ret i64 %D
-  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
   %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
   ret i64 %D
 }
 
-define i64 @ptrtoint_sub_zext_ptrtoint_as2(ptr addrspace(2) %p, i32 %offset) {
+define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2(
+; CHECK-NEXT:  %A.idx = shl nsw i32 %offset, 1
+; CHECK-NEXT:  %E = sext i32 %A.idx to i64
+; CHECK-NEXT:  ret i64 %E
+  %A = getelementptr nusw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %D = zext i32 ptrtoint (ptr addrspace(2) @Arr_as2 to i32) to i64
+  %E = sub i64 %C, %D
+  ret i64 %E
+}
+
+define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(
+; CHECK-NEXT:  %A.idx = shl nuw i32 %offset, 1
+; CHECK-NEXT:  %E = zext i32 %A.idx to i64
+; CHECK-NEXT:  ret i64 %E
+  %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %D = zext i32 ptrtoint (ptr addrspace(2) @Arr_as2 to i32) to i64
+  %E = sub i64 %C, %D
+  ret i64 %E
+}
+
+define i64 @ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
 ; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2(
 ; CHECK-NEXT:  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
 ; CHECK-NEXT:  %B = ptrtoint ptr addrspace(2) %A to i32

>From fa83e47d6ab7138b37f708ea948baeba3c18cbed Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Wed, 13 Nov 2024 21:45:01 -0500
Subject: [PATCH 4/6] Addressed comments

---
 .../InstCombine/InstCombineAddSub.cpp         |  6 +++--
 llvm/test/Transforms/InstCombine/sub-gep.ll   | 27 +++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 40172bf2cd1eb7..fe5e478ef371d2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2631,14 +2631,16 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
                                                /* IsNUW */ false))
       return replaceInstUsesWith(I, Res);
 
-  if (match(Op0, m_ZExt(m_PtrToInt(m_Value(LHSOp)))) &&
+  if (match(Op0, m_ZExt(m_PtrToIntSameSize(DL, m_Value(LHSOp)))) &&
       match(Op1, m_ZExtOrSelf(m_PtrToInt(m_Value(RHSOp))))) {
     if (auto *GEP = dyn_cast<GEPOperator>(LHSOp)) {
       if (GEP->getPointerOperand() == RHSOp) {
         if (GEP->hasNoUnsignedWrap() || GEP->hasNoUnsignedSignedWrap()) {
           Value *Offset = EmitGEPOffset(GEP);
           Value *Res = GEP->hasNoUnsignedWrap()
-                           ? Builder.CreateZExt(Offset, I.getType())
+                           ? Builder.CreateZExt(
+                                 Offset, I.getType(), "",
+                                 /*IsNonNeg=*/GEP->hasNoUnsignedSignedWrap())
                            : Builder.CreateSExt(Offset, I.getType());
           return replaceInstUsesWith(I, Res);
         }
diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index 3a566b4193116a..e6ea0867d7c5e6 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -340,6 +340,18 @@ define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
   ret i64 %D
 }
 
+define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(
+; CHECK-NEXT:  %A.idx = shl nuw nsw i32 %offset, 1
+; CHECK-NEXT:  %D = zext nneg i32 %A.idx to i64
+; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr nusw nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
+  ret i64 %D
+}
+
 define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
 ; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2(
 ; CHECK-NEXT:  %A.idx = shl nsw i32 %offset, 1
@@ -366,6 +378,21 @@ define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(i32 %offset) {
   ret i64 %E
 }
 
+define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
+  ; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(
+  ; CHECK-NEXT:  %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  ; CHECK-NEXT:  %1 = ptrtoint ptr addrspace(2) %A to i32
+  ; CHECK-NEXT:  %B.mask = and i32 %1, 65534
+  ; CHECK-NEXT:  %C = zext nneg i32 %B.mask to i64
+  ; CHECK-NEXT:  %D = sub nsw i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
+  ; CHECK-NEXT:  ret i64 %D
+  %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i16
+  %C = zext i16 %B to i64
+  %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
+  ret i64 %D
+}
+
 define i64 @ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
 ; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2(
 ; CHECK-NEXT:  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset

>From 11090abde0c3dda63f697cb3b62e3e6d588473fa Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Thu, 14 Nov 2024 17:04:43 -0500
Subject: [PATCH 5/6] Updated test

---
 llvm/test/Transforms/InstCombine/sub-gep.ll | 146 +++++++++++++-------
 1 file changed, 94 insertions(+), 52 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index e6ea0867d7c5e6..d711f59ff505e5 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -272,12 +272,13 @@ define i64 @test25(ptr %P, i64 %A){
 
 define i64 @zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint(
-; CHECK-NEXT:  %1 = sext i32 %offset to i64
-; CHECK-NEXT:  %A = getelementptr bfloat, ptr @Arr, i64 %1
-; CHECK-NEXT:  %2 = ptrtoint ptr %A to i64
-; CHECK-NEXT:  %C = and i64 %2, 4294967294
-; CHECK-NEXT:  %D = sub i64 %C, ptrtoint (ptr @Arr to i64)
-; CHECK-NEXT:  ret i64 %D
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
+; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
+; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 4294967294
+; CHECK-NEXT:    [[D:%.*]] = sub i64 [[C]], ptrtoint (ptr @Arr to i64)
+; CHECK-NEXT:    ret i64 [[D]]
+;
   %A = getelementptr bfloat, ptr @Arr, i32 %offset
   %B = ptrtoint ptr %A to i32
   %C = zext i32 %B to i64
@@ -287,12 +288,13 @@ define i64 @zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
 
 define i64 @ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
 ; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint(
-; CHECK-NEXT:  %1 = sext i32 %offset to i64
-; CHECK-NEXT:  %A = getelementptr bfloat, ptr @Arr, i64 %1
-; CHECK-NEXT:  %2 = ptrtoint ptr %A to i64
-; CHECK-NEXT:  %C = and i64 %2, 4294967294
-; CHECK-NEXT:  %D = sub i64 ptrtoint (ptr @Arr to i64), %C
-; CHECK-NEXT:  ret i64 %D
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
+; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
+; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 4294967294
+; CHECK-NEXT:    [[D:%.*]] = sub i64 ptrtoint (ptr @Arr to i64), [[C]]
+; CHECK-NEXT:    ret i64 [[D]]
+;
   %A = getelementptr bfloat, ptr @Arr, i32 %offset
   %B = ptrtoint ptr %A to i32
   %C = zext i32 %B to i64
@@ -300,6 +302,38 @@ define i64 @ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
   ret i64 %D
 }
 
+define i64 @negative_zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
+; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
+; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
+; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 65534
+; CHECK-NEXT:    [[D:%.*]] = sub i64 [[C]], ptrtoint (ptr @Arr to i64)
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr bfloat, ptr @Arr, i32 %offset
+  %B = ptrtoint ptr %A to i16
+  %C = zext i16 %B to i64
+  %D = sub i64 %C, ptrtoint (ptr @Arr to i64)
+  ret i64 %D
+}
+
+define i64 @negative_ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
+; CHECK-LABEL: @negative_ptrtoint_sub_zext_ptrtoint(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
+; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
+; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 65534
+; CHECK-NEXT:    [[D:%.*]] = sub i64 ptrtoint (ptr @Arr to i64), [[C]]
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr bfloat, ptr @Arr, i32 %offset
+  %B = ptrtoint ptr %A to i16
+  %C = zext i16 %B to i64
+  %D = sub i64 ptrtoint (ptr @Arr to i64), %C
+  ret i64 %D
+}
+
 @Arr_as1 = external addrspace(1) global [42 x i16]
 
 define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
@@ -316,11 +350,28 @@ define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
 }
 
 @Arr_as2 = external addrspace(2) global [42 x i16]
-define i64 @zext_ptrtoint_sub_ptrtoint_as2(i32 %offset) {
-; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2(
-; CHECK-NEXT:  %A.idx = shl nsw i32 %offset, 1
-; CHECK-NEXT:  %D = sext i32 %A.idx to i64
-; CHECK-NEXT:  ret i64 %D
+
+define i64 @ptrtoint_sub_zext_ptrtoint_as2_inbounds(i32 %offset) {
+; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2_inbounds(
+; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 [[OFFSET:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
+; CHECK-NEXT:    [[C:%.*]] = zext i32 [[B]] to i64
+; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), [[C]]
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %D = sub i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), %C
+  ret i64 %D
+}
+
+define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw(i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[D:%.*]] = sext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[D]]
+;
   %A = getelementptr nusw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
@@ -330,9 +381,10 @@ define i64 @zext_ptrtoint_sub_ptrtoint_as2(i32 %offset) {
 
 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nuw(
-; CHECK-NEXT:  %A.idx = shl nuw i32 %offset, 1
-; CHECK-NEXT:  %D = zext i32 %A.idx to i64
-; CHECK-NEXT:  ret i64 %D
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[D:%.*]] = zext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[D]]
+;
   %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
@@ -342,9 +394,10 @@ define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
 
 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(i32 %offset) {
 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(
-; CHECK-NEXT:  %A.idx = shl nuw nsw i32 %offset, 1
-; CHECK-NEXT:  %D = zext nneg i32 %A.idx to i64
-; CHECK-NEXT:  ret i64 %D
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[D:%.*]] = zext nneg i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[D]]
+;
   %A = getelementptr nusw nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
@@ -352,11 +405,12 @@ define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(i32 %offset) {
   ret i64 %D
 }
 
-define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
-; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2(
-; CHECK-NEXT:  %A.idx = shl nsw i32 %offset, 1
-; CHECK-NEXT:  %E = sext i32 %A.idx to i64
-; CHECK-NEXT:  ret i64 %E
+define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw(i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[E:%.*]] = sext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[E]]
+;
   %A = getelementptr nusw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
@@ -367,9 +421,10 @@ define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
 
 define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(i32 %offset) {
 ; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(
-; CHECK-NEXT:  %A.idx = shl nuw i32 %offset, 1
-; CHECK-NEXT:  %E = zext i32 %A.idx to i64
-; CHECK-NEXT:  ret i64 %E
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[E:%.*]] = zext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[E]]
+;
   %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i32
   %C = zext i32 %B to i64
@@ -379,13 +434,14 @@ define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(i32 %offset) {
 }
 
 define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
-  ; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(
-  ; CHECK-NEXT:  %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
-  ; CHECK-NEXT:  %1 = ptrtoint ptr addrspace(2) %A to i32
-  ; CHECK-NEXT:  %B.mask = and i32 %1, 65534
-  ; CHECK-NEXT:  %C = zext nneg i32 %B.mask to i64
-  ; CHECK-NEXT:  %D = sub nsw i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
-  ; CHECK-NEXT:  ret i64 %D
+; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(
+; CHECK-NEXT:    [[A:%.*]] = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 [[OFFSET:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
+; CHECK-NEXT:    [[B_MASK:%.*]] = and i32 [[TMP1]], 65534
+; CHECK-NEXT:    [[C:%.*]] = zext nneg i32 [[B_MASK]] to i64
+; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 [[C]], ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
+; CHECK-NEXT:    ret i64 [[D]]
+;
   %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
   %B = ptrtoint ptr addrspace(2) %A to i16
   %C = zext i16 %B to i64
@@ -393,20 +449,6 @@ define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
   ret i64 %D
 }
 
-define i64 @ptrtoint_sub_zext_ptrtoint_as2(i32 %offset) {
-; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2(
-; CHECK-NEXT:  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
-; CHECK-NEXT:  %B = ptrtoint ptr addrspace(2) %A to i32
-; CHECK-NEXT:  %C = zext i32 %B to i64
-; CHECK-NEXT:  %D = sub nsw i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), %C
-; CHECK-NEXT:  ret i64 %D
-  %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
-  %B = ptrtoint ptr addrspace(2) %A to i32
-  %C = zext i32 %B to i64
-  %D = sub i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), %C
-  ret i64 %D
-}
-
 define i64 @test30(ptr %foo, i64 %i, i64 %j) {
 ; CHECK-LABEL: @test30(
 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2

>From 987bfd9a3f37959d60a04ee1fd636a3946f657b4 Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Thu, 14 Nov 2024 20:11:16 -0500
Subject: [PATCH 6/6] Added identical test that use non-global ptr

---
 llvm/test/Transforms/InstCombine/sub-gep.ll | 109 ++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index d711f59ff505e5..f7a54ab2141bd7 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -449,6 +449,115 @@ define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
   ret i64 %D
 }
 
+define i64 @ptrtoint_sub_zext_ptrtoint_as2_inbounds_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2_inbounds_local(
+; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds bfloat, ptr addrspace(2) [[P:%.*]], i32 [[OFFSET:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
+; CHECK-NEXT:    [[C:%.*]] = zext i32 [[B]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(2) [[P]] to i32
+; CHECK-NEXT:    [[CC:%.*]] = zext i32 [[TMP1]] to i64
+; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 [[CC]], [[C]]
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr inbounds bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i64
+  %D = sub i64 %CC, %C
+  ret i64 %D
+}
+
+define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_local(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[D:%.*]] = sext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr nusw bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i64
+  %D = sub i64 %C, %CC
+  ret i64 %D
+}
+
+define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nuw_local(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[D:%.*]] = zext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr nuw bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i64
+  %D = sub i64 %C, %CC
+  ret i64 %D
+}
+
+define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw_local(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[D:%.*]] = zext nneg i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr nusw nuw bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i64
+  %D = sub i64 %C, %CC
+  ret i64 %D
+}
+
+define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw_local(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[E:%.*]] = sext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[E]]
+;
+  %A = getelementptr nusw bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i32
+  %D = zext i32 %CC to i64
+  %E = sub i64 %C, %D
+  ret i64 %E
+}
+
+define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw_local(
+; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
+; CHECK-NEXT:    [[E:%.*]] = zext i32 [[A_IDX]] to i64
+; CHECK-NEXT:    ret i64 [[E]]
+;
+  %A = getelementptr nuw bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i32
+  %C = zext i32 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i32
+  %D = zext i32 %CC to i64
+  %E = sub i64 %C, %D
+  ret i64 %E
+}
+
+define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw_local(ptr addrspace(2) %p, i32 %offset) {
+; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw_local(
+; CHECK-NEXT:    [[A:%.*]] = getelementptr nuw bfloat, ptr addrspace(2) [[P:%.*]], i32 [[OFFSET:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
+; CHECK-NEXT:    [[B_MASK:%.*]] = and i32 [[TMP1]], 65535
+; CHECK-NEXT:    [[C:%.*]] = zext nneg i32 [[B_MASK]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr addrspace(2) [[P]] to i32
+; CHECK-NEXT:    [[CC:%.*]] = zext i32 [[TMP2]] to i64
+; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 [[C]], [[CC]]
+; CHECK-NEXT:    ret i64 [[D]]
+;
+  %A = getelementptr nuw bfloat, ptr addrspace(2) %p, i32 %offset
+  %B = ptrtoint ptr addrspace(2) %A to i16
+  %C = zext i16 %B to i64
+  %CC = ptrtoint ptr addrspace(2) %p to i64
+  %D = sub i64 %C, %CC
+  ret i64 %D
+}
+
 define i64 @test30(ptr %foo, i64 %i, i64 %j) {
 ; CHECK-LABEL: @test30(
 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2



More information about the llvm-commits mailing list