diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2087,11 +2087,23 @@ if (!GEP.accumulateConstantOffset(DL, Offset)) return nullptr; + APInt OffsetOld = Offset; // Convert the total offset back into indices. SmallVector ConstIndices = DL.getGEPIndicesForOffset(BaseType, Offset); - if (!Offset.isZero() || (!IsFirstType && !ConstIndices[0].isZero())) + if (!Offset.isZero() || (!IsFirstType && !ConstIndices[0].isZero())) { + // If both GEP are constant-indexed, and cannot be merged in either way, + // convert them to a GEP of i8. + if (Src->hasAllConstantIndices()) + return isMergedGEPInBounds(*Src, *cast(&GEP)) + ? GetElementPtrInst::CreateInBounds( + Builder.getInt8Ty(), Src->getOperand(0), + Builder.getInt(OffsetOld), GEP.getName()) + : GetElementPtrInst::Create( + Builder.getInt8Ty(), Src->getOperand(0), + Builder.getInt(OffsetOld), GEP.getName()); return nullptr; + } SmallVector Indices; append_range(Indices, drop_end(Src->indices(), diff --git a/llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll b/llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll --- a/llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll +++ b/llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll @@ -56,9 +56,8 @@ ; result = (i8*) p + 14 define ptr @array2(ptr %p, i64 %a) { ; CHECK-LABEL: @array2( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [7 x i32], ptr [[P:%.*]], i64 0, i64 3 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 2 -; CHECK-NEXT: ret ptr [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 14 +; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = getelementptr inbounds [7 x i32], ptr %p, i64 0, i64 3 %2 = getelementptr inbounds i8, ptr %1, i64 2 @@ -68,9 +67,8 @@ ; result = (i8*) p + 20 define ptr @array3(ptr %p) { ; CHECK-LABEL: @array3( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 2 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP1]], i64 1, i64 1 -; CHECK-NEXT: ret ptr [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 20 +; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = getelementptr inbounds i64, ptr %p, i64 2 %2 = getelementptr inbounds [3 x i8], ptr %1, i64 1, i64 1 @@ -80,9 +78,8 @@ ; result = (i8*) p + 36 define ptr @struct1(ptr %p) { ; CHECK-LABEL: @struct1( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 3 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[TMP1]], i64 1 -; CHECK-NEXT: ret ptr [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 36 +; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = getelementptr inbounds i64, ptr %p, i64 3 %2 = getelementptr inbounds %struct.C, ptr %1, i64 1 @@ -141,9 +138,8 @@ ; result = &((struct.C*) p + 2).member1 define ptr @structMemberAliasing(ptr %p, i64 %a) { ; CHECK-LABEL: @structMemberAliasing( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 1 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[TMP1]], i64 1, i32 2 -; CHECK-NEXT: ret ptr [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 28 +; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = getelementptr inbounds i64, ptr %p, i64 1 %2 = getelementptr inbounds %struct.C, ptr %1, i64 1, i32 2 @@ -154,9 +150,8 @@ ; 8-bit aligned. define ptr @notDivisible(ptr %p) { ; CHECK-LABEL: @notDivisible( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i24, ptr [[P:%.*]], i64 1 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1 -; CHECK-NEXT: ret ptr [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 7 +; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = getelementptr inbounds i24, ptr %p, i64 1 %2 = getelementptr inbounds i32, ptr %1, i64 1 diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll --- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll +++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll @@ -211,8 +211,7 @@ define ptr @geps_combinable_different_elem_type4(ptr %a) { ; CHECK-LABEL: @geps_combinable_different_elem_type4( -; CHECK-NEXT: [[A2:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 0, i32 1 -; CHECK-NEXT: [[A3:%.*]] = getelementptr i8, ptr [[A2]], i64 10 +; CHECK-NEXT: [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 14 ; CHECK-NEXT: ret ptr [[A3]] ; %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1