[llvm] 55cf09a - [ValueTracking] Simplify llvm::isPointerOffset()

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 14 09:32:50 PDT 2022


Author: Arthur Eubanks
Date: 2022-03-14T09:32:36-07:00
New Revision: 55cf09ae2600066045ad9f9d81b330bc4d52b7e4

URL: https://github.com/llvm/llvm-project/commit/55cf09ae2600066045ad9f9d81b330bc4d52b7e4
DIFF: https://github.com/llvm/llvm-project/commit/55cf09ae2600066045ad9f9d81b330bc4d52b7e4.diff

LOG: [ValueTracking] Simplify llvm::isPointerOffset()

We still need the code after stripAndAccumulateConstantOffsets() since
it doesn't handle GEPs of scalable types and non-constant but identical
indexes.

Differential Revision: https://reviews.llvm.org/D120523

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 80e0d922edad1..457e1b24749b5 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7097,60 +7097,18 @@ getOffsetFromIndex(const GEPOperator *GEP, unsigned Idx, const DataLayout &DL) {
 
 Optional<int64_t> llvm::isPointerOffset(const Value *Ptr1, const Value *Ptr2,
                                         const DataLayout &DL) {
-  Ptr1 = Ptr1->stripPointerCasts();
-  Ptr2 = Ptr2->stripPointerCasts();
+  APInt Offset1(DL.getIndexTypeSizeInBits(Ptr1->getType()), 0);
+  APInt Offset2(DL.getIndexTypeSizeInBits(Ptr2->getType()), 0);
+  Ptr1 = Ptr1->stripAndAccumulateConstantOffsets(DL, Offset1, true);
+  Ptr2 = Ptr2->stripAndAccumulateConstantOffsets(DL, Offset2, true);
 
   // Handle the trivial case first.
-  if (Ptr1 == Ptr2) {
-    return 0;
-  }
+  if (Ptr1 == Ptr2)
+    return Offset2.getSExtValue() - Offset1.getSExtValue();
 
   const GEPOperator *GEP1 = dyn_cast<GEPOperator>(Ptr1);
   const GEPOperator *GEP2 = dyn_cast<GEPOperator>(Ptr2);
 
-  // If one pointer is a GEP see if the GEP is a constant offset from the base,
-  // as in "P" and "gep P, 1".
-  // Also do this iteratively to handle the the following case:
-  //   Ptr_t1 = GEP Ptr1, c1
-  //   Ptr_t2 = GEP Ptr_t1, c2
-  //   Ptr2 = GEP Ptr_t2, c3
-  // where we will return c1+c2+c3.
-  // TODO: Handle the case when both Ptr1 and Ptr2 are GEPs of some common base
-  // -- replace getOffsetFromBase with getOffsetAndBase, check that the bases
-  // are the same, and return the 
diff erence between offsets.
-  auto getOffsetFromBase = [&DL](const GEPOperator *GEP,
-                                 const Value *Ptr) -> Optional<int64_t> {
-    const GEPOperator *GEP_T = GEP;
-    int64_t OffsetVal = 0;
-    bool HasSameBase = false;
-    while (GEP_T) {
-      auto Offset = getOffsetFromIndex(GEP_T, 1, DL);
-      if (!Offset)
-        return None;
-      OffsetVal += *Offset;
-      auto Op0 = GEP_T->getOperand(0)->stripPointerCasts();
-      if (Op0 == Ptr) {
-        HasSameBase = true;
-        break;
-      }
-      GEP_T = dyn_cast<GEPOperator>(Op0);
-    }
-    if (!HasSameBase)
-      return None;
-    return OffsetVal;
-  };
-
-  if (GEP1) {
-    auto Offset = getOffsetFromBase(GEP1, Ptr2);
-    if (Offset)
-      return -*Offset;
-  }
-  if (GEP2) {
-    auto Offset = getOffsetFromBase(GEP2, Ptr1);
-    if (Offset)
-      return Offset;
-  }
-
   // Right now we handle the case when Ptr1/Ptr2 are both GEPs with an identical
   // base.  After that base, they may have some number of common (and
   // potentially variable) indices.  After that they handle some constant
@@ -7166,9 +7124,10 @@ Optional<int64_t> llvm::isPointerOffset(const Value *Ptr1, const Value *Ptr2,
     if (GEP1->getOperand(Idx) != GEP2->getOperand(Idx))
       break;
 
-  auto Offset1 = getOffsetFromIndex(GEP1, Idx, DL);
-  auto Offset2 = getOffsetFromIndex(GEP2, Idx, DL);
-  if (!Offset1 || !Offset2)
+  auto IOffset1 = getOffsetFromIndex(GEP1, Idx, DL);
+  auto IOffset2 = getOffsetFromIndex(GEP2, Idx, DL);
+  if (!IOffset1 || !IOffset2)
     return None;
-  return *Offset2 - *Offset1;
+  return *IOffset2 - *IOffset1 + Offset2.getSExtValue() -
+         Offset1.getSExtValue();
 }

diff  --git a/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll b/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll
index 470775c05f4c9..65733830d5629 100644
--- a/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll
+++ b/llvm/test/Transforms/MemCpyOpt/opaque-ptr.ll
@@ -22,10 +22,9 @@ define void @test_memset_memcpy(ptr %src, i64 %src_size, ptr noalias %dst, i64 %
 define void @test_
diff erent_gep_source_elements(ptr %src) {
 ; CHECK-LABEL: @test_
diff erent_gep_source_elements(
 ; CHECK-NEXT:    [[PB:%.*]] = getelementptr [[B:%.*]], ptr [[SRC:%.*]], i64 0, i32 1
-; CHECK-NEXT:    store i64 0, ptr [[PB]], align 4
 ; CHECK-NEXT:    [[PA:%.*]] = getelementptr [[A:%.*]], ptr [[SRC]], i64 0, i32 1
 ; CHECK-NEXT:    [[PA2:%.*]] = getelementptr [[A]], ptr [[SRC]], i64 0, i32 2
-; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[PA]], i8 0, i64 16, i1 false)
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[PB]], i8 0, i64 20, i1 false)
 ; CHECK-NEXT:    ret void
 ;
   %pb = getelementptr %b, ptr %src, i64 0, i32 1
@@ -37,5 +36,23 @@ define void @test_
diff erent_gep_source_elements(ptr %src) {
   ret void
 }
 
+define void @test_gep_of_vscale_non_const_gep(ptr %p, i64 %idx) {
+; CHECK-LABEL: @test_gep_of_vscale_non_const_gep(
+; CHECK-NEXT:    [[G1:%.*]] = getelementptr <vscale x 16 x i8>, ptr [[P:%.*]], i64 [[IDX:%.*]], i32 1
+; CHECK-NEXT:    [[G2:%.*]] = getelementptr <vscale x 16 x i8>, ptr [[P]], i64 [[IDX]], i32 5
+; CHECK-NEXT:    [[H1:%.*]] = getelementptr i8, ptr [[G1]], i64 2
+; CHECK-NEXT:    [[H2:%.*]] = getelementptr i8, ptr [[G2]], i64 6
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[H1]], i8 0, i64 16, i1 false)
+; CHECK-NEXT:    ret void
+;
+  %g1 = getelementptr <vscale x 16 x i8>, ptr %p, i64 %idx, i32 1
+  %g2 = getelementptr <vscale x 16 x i8>, ptr %p, i64 %idx, i32 5
+  %h1 = getelementptr i8, ptr %g1, i64 2
+  %h2 = getelementptr i8, ptr %g2, i64 6
+  store i64 0, ptr %h1
+  store i64 0, ptr %h2
+  ret void
+}
+
 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)
 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)


        


More information about the llvm-commits mailing list