diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4094,7 +4094,7 @@ if (!IsScalableVec && Ty->isSized()) { Value *P; uint64_t C; - uint64_t TyAllocSize = Q.DL.getTypeAllocSize(Ty); + uint64_t TyAllocSize = Q.DL.getTypeAllocSize(Ty).getFixedSize(); // getelementptr P, N -> P if P points to a type of zero size. if (TyAllocSize == 0 && Ops[0]->getType() == GEPTy) return Ops[0]; @@ -4139,12 +4139,16 @@ } } - if (!IsScalableVec && Q.DL.getTypeAllocSize(LastType) == 1 && + // The following folds are only valid when GEP index types are scalar types. + // Bailout early if GEP index type is vector type. + if (!IsScalableVec && !isa(Ops.back()->getType()) && + Q.DL.getTypeAllocSize(LastType).getFixedSize() == 1 && all_of(Ops.slice(1).drop_back(1), [](Value *Idx) { return match(Idx, m_Zero()); })) { unsigned IdxWidth = Q.DL.getIndexSizeInBits(Ops[0]->getType()->getPointerAddressSpace()); - if (Q.DL.getTypeSizeInBits(Ops.back()->getType()) == IdxWidth) { + if (Q.DL.getTypeSizeInBits(Ops.back()->getType()).getFixedSize() == + IdxWidth) { APInt BasePtrOffset(IdxWidth, 0); Value *StrippedBasePtr = Ops[0]->stripAndAccumulateInBoundsConstantOffsets(Q.DL, diff --git a/llvm/test/Transforms/InstSimplify/cast.ll b/llvm/test/Transforms/InstSimplify/cast.ll --- a/llvm/test/Transforms/InstSimplify/cast.ll +++ b/llvm/test/Transforms/InstSimplify/cast.ll @@ -27,6 +27,7 @@ ; CHECK: ret i8* %V } +; This test checks for fold "gep (gep V, C), (sub 0, V) -> C" define i32 @test4() { ; CHECK-LABEL: @test4( %alloca = alloca i32, align 4 ; alloca + 0 @@ -40,6 +41,7 @@ ; CHECK-NEXT: ret i32 4 } +; This test checks for fold "gep (gep V, C), (xor V, -1) -> C-1" define i32 @test5() { ; CHECK-LABEL: @test5( %alloca = alloca i32, align 4 ; alloca + 0 @@ -48,7 +50,27 @@ %pti = ptrtoint i32* %alloca to i32 ; alloca %sub = xor i32 %pti, -1 ; ~alloca %add = getelementptr [4 x i8], [4 x i8]* %bc, i32 0, i32 %sub ; alloca + 4 - alloca - 1 == 3 - %add_to_int = ptrtoint i8* %add to i32 ; 4 - ret i32 %add_to_int ; 4 + %add_to_int = ptrtoint i8* %add to i32 ; 3 + ret i32 %add_to_int ; 3 ; CHECK-NEXT: ret i32 3 } + +; Negative tests + +; The above folds are only valid when gep index type is scalar type. These negative +; tests check the folding codepath won't be executed, and assertion won't be triggered +; that we are not trying to get fixed size on a scalable type. + +define <1 x i8*> @gep_index_vector(i8* %a, <1 x i32> %offset) { +; CHECK-LABEL: @gep_index_vector + %v = getelementptr i8, i8* %a, <1 x i32> %offset + ret <1 x i8*> %v +; CHECK: ret <1 x i8*> %v +} + +define @gep_index_vector_scalable(i8* %a, %offset) { +; CHECK-LABEL: @gep_index_vector_scalable + %v = getelementptr i8, i8* %a, %offset + ret %v +; CHECK: ret %v +}