Index: llvm/lib/IR/ConstantFold.cpp =================================================================== --- llvm/lib/IR/ConstantFold.cpp +++ llvm/lib/IR/ConstantFold.cpp @@ -1998,32 +1998,14 @@ I != E; ++I) LastI = I; - // We cannot combine indices if doing so would take us outside of an - // array or vector. Doing otherwise could trick us if we evaluated such a - // GEP as part of a load. - // - // e.g. Consider if the original GEP was: - // i8* getelementptr ({ [2 x i8], i32, i8, [3 x i8] }* @main.c, - // i32 0, i32 0, i64 0) - // - // If we then tried to offset it by '8' to get to the third element, - // an i8, we should *not* get: - // i8* getelementptr ({ [2 x i8], i32, i8, [3 x i8] }* @main.c, - // i32 0, i32 0, i64 8) - // - // This GEP tries to index array element '8 which runs out-of-bounds. - // Subsequent evaluation would get confused and produce erroneous results. - // - // The following prohibits such a GEP from being formed by checking to see - // if the index is in-range with respect to an array. + // We can't combine GEPs if the last index is a struct type. if (!LastI.isSequential()) return nullptr; + // We could perform the transform with non-constant index, but prefer leaving + // it as GEP of GEP rather than GEP of add for now. ConstantInt *CI = dyn_cast(Idx0); if (!CI) return nullptr; - if (LastI.isBoundedSequential() && - !isIndexInRangeOfArrayType(LastI.getSequentialNumElements(), CI)) - return nullptr; // TODO: This code may be extended to handle vectors as well. auto *LastIdx = cast(GEP->getOperand(GEP->getNumOperands()-1)); Index: llvm/test/Transforms/SCCP/apint-bigint2.ll =================================================================== --- llvm/test/Transforms/SCCP/apint-bigint2.ll +++ llvm/test/Transforms/SCCP/apint-bigint2.ll @@ -54,7 +54,7 @@ define void @index_too_large() { ; CHECK-LABEL: @index_too_large( -; CHECK-NEXT: store i101* getelementptr (i101, i101* getelementptr ([6 x i101], [6 x i101]* @Y, i32 0, i32 -1), i101 9224497936761618431), i101** undef, align 8 +; CHECK-NEXT: store i101* getelementptr ([6 x i101], [6 x i101]* @Y, i101 1537416322793603071, i101 4), i101** undef, align 8 ; CHECK-NEXT: ret void ; %ptr1 = getelementptr [6 x i101], [6 x i101]* @Y, i32 0, i32 -1 Index: llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll =================================================================== --- llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll +++ llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll @@ -8,10 +8,10 @@ ; CHECK-LABEL: @eq_undereferenceable( ; CHECK-NEXT: entry: ; CHECK-NEXT: store i32 1, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0), align 4 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[P:%.*]], getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[P:%.*]], getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0) ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: -; CHECK-NEXT: store i32 2, i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1), align 4 +; CHECK-NEXT: store i32 2, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0), align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0), align 4 @@ -62,13 +62,13 @@ define i1 @eq_undereferenceable_cmp_simp(i32* %p) { ; CHECK-LABEL: @eq_undereferenceable_cmp_simp( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP_0:%.*]] = icmp eq i32* [[P:%.*]], getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1) +; CHECK-NEXT: [[CMP_0:%.*]] = icmp eq i32* [[P:%.*]], getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0) ; CHECK-NEXT: br i1 [[CMP_0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: -; CHECK-NEXT: store i32 2, i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1), align 4 +; CHECK-NEXT: store i32 2, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0), align 4 ; CHECK-NEXT: ret i1 true ; CHECK: if.end: -; CHECK-NEXT: [[CMP_2:%.*]] = icmp eq i32* [[P]], getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1) +; CHECK-NEXT: [[CMP_2:%.*]] = icmp eq i32* [[P]], getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0) ; CHECK-NEXT: ret i1 [[CMP_2]] ; entry: