diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp --- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp +++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp @@ -817,6 +817,12 @@ gep_type_iterator GTI = gep_type_begin(*GEP); for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I, ++GTI) { if (GTI.isSequential()) { + TypeSize AllocSize = DL->getTypeAllocSize(GTI.getIndexedType()); + + // Constant offsets of scalable types are not really constant. + if (AllocSize.isScalable()) + continue; + // Tries to extract a constant offset from this GEP index. int64_t ConstantOffset = ConstantOffsetExtractor::Find(GEP->getOperand(I), GEP, DT); @@ -825,8 +831,7 @@ // A GEP may have multiple indices. We accumulate the extracted // constant offset to a byte offset, and later offset the remainder of // the original GEP with this byte offset. - AccumulativeByteOffset += - ConstantOffset * DL->getTypeAllocSize(GTI.getIndexedType()); + AccumulativeByteOffset += ConstantOffset * AllocSize; } } else if (LowerGEP) { StructType *StTy = GTI.getStructType(); @@ -1006,6 +1011,10 @@ gep_type_iterator GTI = gep_type_begin(*GEP); for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I, ++GTI) { if (GTI.isSequential()) { + // Constant offsets of scalable types are not really constant. + if (DL->getTypeAllocSize(GTI.getIndexedType()).isScalable()) + continue; + // Splits this GEP index into a variadic part and a constant offset, and // uses the variadic part as the new index. Value *OldIdx = GEP->getOperand(I); diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=separate-const-offset-from-gep < %s | FileCheck %s + +target triple = "aarch64-linux-gnu" + +; Index is implicitly multiplied by vscale and so not really constant. +define ptr @test1(ptr %base, i64 %idx) #0 { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[IDX_NEXT:%.*]] = add nuw nsw i64 [[IDX:%.*]], 1 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr , ptr [[BASE:%.*]], i64 [[IDX_NEXT]] +; CHECK-NEXT: ret ptr [[GEP]] +; + %idx.next = add nuw nsw i64 %idx, 1 + %gep = getelementptr , ptr %base, i64 %idx.next + ret ptr %gep +} + +; Whilst the first index is not constant, the calculation of the second index +; does contain a constant that can be extracted. +define ptr @test2(ptr %base, i64 %idx) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE:%.*]], i64 3, i64 [[IDX:%.*]] +; CHECK-NEXT: [[GEP2:%.*]] = getelementptr float, ptr [[TMP1]], i64 1 +; CHECK-NEXT: ret ptr [[GEP2]] +; + %idx.next = add nuw nsw i64 %idx, 1 + %gep = getelementptr , ptr %base, i64 3, i64 %idx.next + ret ptr %gep +} + +attributes #0 = { "target-features"="+sve" }