forked from OSchip/llvm-project
[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.
This commit is contained in:
parent
d092df42f3
commit
3c9f3f76f1
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue