[llvm] 3c9f3f7 - [ConstantFold] Fold zero-index GEPs with opaque pointers

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 4 04:04:39 PDT 2022


Author: Nikita Popov
Date: 2022-04-04T13:04:27+02:00
New Revision: 3c9f3f76f105196cd354a34f597b1ce88bee9b5d

URL: https://github.com/llvm/llvm-project/commit/3c9f3f76f105196cd354a34f597b1ce88bee9b5d
DIFF: https://github.com/llvm/llvm-project/commit/3c9f3f76f105196cd354a34f597b1ce88bee9b5d.diff

LOG: [ConstantFold] Fold zero-index GEPs with opaque pointers

With opaque pointers, we can eliminate zero-index GEPs even if
they have multiple indices, as this no longer impacts the result
type of the GEP.

This optimization is already done for instructions in InstSimplify,
but we were missing the corresponding constant expression handling.

The constexpr transform is a bit more powerful, because it can
produce a vector splat constant and also handles undef values --
it is an extension of an existing single-index transform.

Added: 
    

Modified: 
    llvm/lib/IR/ConstantFold.cpp
    llvm/test/Transforms/IndVarSimplify/lftr-opaque-pointers.ll
    llvm/test/Transforms/InstSimplify/opaque-ptr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 74200b99367ca..e38cd820da29f 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -2036,8 +2036,18 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
     // If inbounds, we can choose an out-of-bounds pointer as a base pointer.
     return InBounds ? PoisonValue::get(GEPTy) : UndefValue::get(GEPTy);
 
-  Constant *Idx0 = cast<Constant>(Idxs[0]);
-  if (Idxs.size() == 1 && (Idx0->isNullValue() || isa<UndefValue>(Idx0)))
+  auto IsNoOp = [&]() {
+    // For non-opaque pointers having multiple indices will change the result
+    // type of the GEP.
+    if (!C->getType()->getScalarType()->isOpaquePointerTy() && Idxs.size() != 1)
+      return false;
+
+    return all_of(Idxs, [](Value *Idx) {
+      Constant *IdxC = cast<Constant>(Idx);
+      return IdxC->isNullValue() || isa<UndefValue>(IdxC);
+    });
+  };
+  if (IsNoOp())
     return GEPTy->isVectorTy() && !C->getType()->isVectorTy()
                ? ConstantVector::getSplat(
                      cast<VectorType>(GEPTy)->getElementCount(), C)
@@ -2090,6 +2100,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
     //   i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
     //
     // Don't fold if the cast is changing address spaces.
+    Constant *Idx0 = cast<Constant>(Idxs[0]);
     if (CE->isCast() && Idxs.size() > 1 && Idx0->isNullValue()) {
       PointerType *SrcPtrTy =
         dyn_cast<PointerType>(CE->getOperand(0)->getType());

diff  --git a/llvm/test/Transforms/IndVarSimplify/lftr-opaque-pointers.ll b/llvm/test/Transforms/IndVarSimplify/lftr-opaque-pointers.ll
index 94e0288e534b1..4edcf5b3414e1 100644
--- a/llvm/test/Transforms/IndVarSimplify/lftr-opaque-pointers.ll
+++ b/llvm/test/Transforms/IndVarSimplify/lftr-opaque-pointers.ll
@@ -11,7 +11,7 @@ define void @test_zext(ptr %a) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[P_0:%.*]] = phi ptr [ getelementptr inbounds ([240 x i8], ptr @data, i64 0, i64 0), [[ENTRY:%.*]] ], [ [[T3:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[P_0:%.*]] = phi ptr [ @data, [[ENTRY:%.*]] ], [ [[T3:%.*]], [[LOOP]] ]
 ; CHECK-NEXT:    [[DOT0:%.*]] = phi ptr [ [[A:%.*]], [[ENTRY]] ], [ [[T:%.*]], [[LOOP]] ]
 ; CHECK-NEXT:    [[T]] = getelementptr inbounds i8, ptr [[DOT0]], i64 1
 ; CHECK-NEXT:    [[T2:%.*]] = load i8, ptr [[DOT0]], align 1

diff  --git a/llvm/test/Transforms/InstSimplify/opaque-ptr.ll b/llvm/test/Transforms/InstSimplify/opaque-ptr.ll
index 30c81b1065b21..d0d3ac1128e67 100644
--- a/llvm/test/Transforms/InstSimplify/opaque-ptr.ll
+++ b/llvm/test/Transforms/InstSimplify/opaque-ptr.ll
@@ -56,56 +56,56 @@ define <2 x ptr> @vector_base_scalar_index(<2 x ptr> %p) {
 
 define ptr @constexpr_zero_gep_scalar_base_scalar_index() {
 ; CHECK-LABEL: @constexpr_zero_gep_scalar_base_scalar_index(
-; CHECK-NEXT:    ret ptr getelementptr inbounds ([2 x i32], ptr @g, i64 0, i64 0)
+; CHECK-NEXT:    ret ptr @g
 ;
   ret ptr getelementptr ([2 x i32], ptr @g, i64 0, i64 0)
 }
 
 define <2 x ptr> @constexpr_zero_gep_vector_base_scalar_index() {
 ; CHECK-LABEL: @constexpr_zero_gep_vector_base_scalar_index(
-; CHECK-NEXT:    ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, <2 x i64> zeroinitializer, <2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <2 x ptr> <ptr @g, ptr @g>
 ;
   ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, i64 0, i64 0)
 }
 
 define <2 x ptr> @constexpr_zero_gep_scalar_base_vector_index() {
 ; CHECK-LABEL: @constexpr_zero_gep_scalar_base_vector_index(
-; CHECK-NEXT:    ret <2 x ptr> getelementptr ([2 x i32], ptr @g, <2 x i64> zeroinitializer, <2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <2 x ptr> <ptr @g, ptr @g>
 ;
   ret <2 x ptr> getelementptr ([2 x i32], ptr @g, <2 x i64> zeroinitializer, i64 0)
 }
 
 define <2 x ptr> @constexpr_zero_gep_vector_base_vector_index() {
 ; CHECK-LABEL: @constexpr_zero_gep_vector_base_vector_index(
-; CHECK-NEXT:    ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, <2 x i64> zeroinitializer, <2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <2 x ptr> <ptr @g, ptr @g>
 ;
   ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, <2 x i64> zeroinitializer, i64 0)
 }
 
 define ptr @constexpr_undef_gep_scalar_base_scalar_index() {
 ; CHECK-LABEL: @constexpr_undef_gep_scalar_base_scalar_index(
-; CHECK-NEXT:    ret ptr getelementptr ([2 x i32], ptr @g, i64 0, i64 undef)
+; CHECK-NEXT:    ret ptr @g
 ;
   ret ptr getelementptr ([2 x i32], ptr @g, i64 0, i64 undef)
 }
 
 define <2 x ptr> @constexpr_undef_gep_vector_base_scalar_index() {
 ; CHECK-LABEL: @constexpr_undef_gep_vector_base_scalar_index(
-; CHECK-NEXT:    ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, <2 x i64> undef, <2 x i64> undef)
+; CHECK-NEXT:    ret <2 x ptr> <ptr @g, ptr @g>
 ;
   ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, i64 undef, i64 undef)
 }
 
 define <2 x ptr> @constexpr_undef_gep_scalar_base_vector_index() {
 ; CHECK-LABEL: @constexpr_undef_gep_scalar_base_vector_index(
-; CHECK-NEXT:    ret <2 x ptr> getelementptr ([2 x i32], ptr @g, <2 x i64> undef, <2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <2 x ptr> <ptr @g, ptr @g>
 ;
   ret <2 x ptr> getelementptr ([2 x i32], ptr @g, <2 x i64> undef, i64 0)
 }
 
 define <2 x ptr> @constexpr_undef_gep_vector_base_vector_index() {
 ; CHECK-LABEL: @constexpr_undef_gep_vector_base_vector_index(
-; CHECK-NEXT:    ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, <2 x i64> undef, <2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <2 x ptr> <ptr @g, ptr @g>
 ;
   ret <2 x ptr> getelementptr ([2 x i32], <2 x ptr> <ptr @g, ptr @g>, <2 x i64> undef, i64 0)
 }


        


More information about the llvm-commits mailing list