[IR] Prefer scalar type for struct indexes in GEP constant expressions.

This has two advantages: one, it's simpler, and two, it doesn't require
heroic pattern matching with scalable vectors.

Also includes a small fix to DataLayout to allow the scalable vector
testcase to work correctly.

Differential Revision: https://reviews.llvm.org/D82061
This commit is contained in:
Eli Friedman 2020-06-17 16:35:35 -07:00
parent 723b5a1785
commit 90ad786947
4 changed files with 21 additions and 8 deletions

View File

@ -2175,15 +2175,20 @@ Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
std::vector<Constant*> ArgVec;
ArgVec.reserve(1 + Idxs.size());
ArgVec.push_back(C);
for (unsigned i = 0, e = Idxs.size(); i != e; ++i) {
auto GTI = gep_type_begin(Ty, Idxs), GTE = gep_type_end(Ty, Idxs);
for (; GTI != GTE; ++GTI) {
auto *Idx = cast<Constant>(GTI.getOperand());
assert(
(!isa<VectorType>(Idxs[i]->getType()) ||
cast<VectorType>(Idxs[i]->getType())->getElementCount() == EltCount) &&
(!isa<VectorType>(Idx->getType()) ||
cast<VectorType>(Idx->getType())->getElementCount() == EltCount) &&
"getelementptr index type missmatch");
Constant *Idx = cast<Constant>(Idxs[i]);
if (EltCount.Min != 0 && !Idxs[i]->getType()->isVectorTy())
if (GTI.isStruct() && Idx->getType()->isVectorTy()) {
Idx = Idx->getSplatValue();
} else if (GTI.isSequential() && EltCount.Min != 0 &&
!Idx->getType()->isVectorTy()) {
Idx = ConstantVector::getSplat(EltCount, Idx);
}
ArgVec.push_back(Idx);
}

View File

@ -814,7 +814,7 @@ Type *DataLayout::getIndexType(Type *Ty) const {
unsigned NumBits = getIndexTypeSizeInBits(Ty);
IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
return FixedVectorType::get(IntTy, VecTy->getNumElements());
return VectorType::get(IntTy, VecTy);
return IntTy;
}

View File

@ -24,7 +24,7 @@ top:
@G = internal global [65 x %struct.A] zeroinitializer, align 16
; CHECK-LABEL: @test
; CHECK: ret <16 x i32*> getelementptr ([65 x %struct.A], [65 x %struct.A]* @G, <16 x i64> zeroinitializer, <16 x i64> <i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15, i64 16>, <16 x i32> zeroinitializer)
; CHECK: ret <16 x i32*> getelementptr ([65 x %struct.A], [65 x %struct.A]* @G, <16 x i64> zeroinitializer, <16 x i64> <i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15, i64 16>, i32 0)
define <16 x i32*> @test() {
vector.body:
%VectorGep = getelementptr [65 x %struct.A], [65 x %struct.A]* @G, <16 x i64> zeroinitializer, <16 x i64> <i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15, i64 16>, <16 x i32> zeroinitializer

View File

@ -152,7 +152,7 @@ define <4 x i32*> @vector_idx_vector() {
%struct = type { double, float }
define <4 x float*> @vector_idx_mix_scalar_vector() {
; CHECK-LABEL: @vector_idx_mix_scalar_vector(
; CHECK-NEXT: ret <4 x float*> getelementptr (%struct, <4 x %struct*> zeroinitializer, <4 x i64> zeroinitializer, <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
; CHECK-NEXT: ret <4 x float*> getelementptr (%struct, <4 x %struct*> zeroinitializer, <4 x i64> zeroinitializer, i32 1)
;
%gep = getelementptr %struct, <4 x %struct*> zeroinitializer, i32 0, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
ret <4 x float*> %gep
@ -168,4 +168,12 @@ define <vscale x 4 x i32*> @scalable_idx_scalar() {
ret <vscale x 4 x i32*> %gep
}
define <vscale x 4 x float*> @scalable_vector_idx_mix_scalar_vector() {
; CHECK-LABEL: @scalable_vector_idx_mix_scalar_vector(
; CHECK-NEXT: ret <vscale x 4 x float*> getelementptr (%struct, <vscale x 4 x %struct*> zeroinitializer, <vscale x 4 x i64> zeroinitializer, i32 1)
;
%gep = getelementptr %struct, <vscale x 4 x %struct*> zeroinitializer, i32 0, i32 1
ret <vscale x 4 x float*> %gep
}
; Check ConstantExpr::getGetElementPtr() using ElementCount for size queries - end.