diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 9bc32e407eee7..aaf07f25e4748 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1887,8 +1887,11 @@ static Instruction *foldSelectGEP(GetElementPtrInst &GEP, Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP, GEPOperator *Src) { // Combine Indices - If the source pointer to this getelementptr instruction - // is a getelementptr instruction, combine the indices of the two - // getelementptr instructions into a single instruction. + // is a getelementptr instruction with matching element type, combine the + // indices of the two getelementptr instructions into a single instruction. + if (Src->getResultElementType() != GEP.getSourceElementType()) + return nullptr; + if (!shouldMergeGEPs(*cast(&GEP), *Src)) return nullptr; diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll index 558aa7c48a383..ab2a109f6103b 100644 --- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll +++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll @@ -161,3 +161,24 @@ define void @varargs_cast_opaque_to_typed(ptr %a) { call void (...) @varargs(i8* byval(i8) %b) ret void } + +define ptr @geps_combinable(ptr %a) { +; CHECK-LABEL: @geps_combinable( +; CHECK-NEXT: [[A3:%.*]] = getelementptr { i32, { i32, i32 } }, ptr [[A:%.*]], i64 0, i32 1, i32 1 +; CHECK-NEXT: ret ptr [[A3]] +; + %a2 = getelementptr { i32, { i32, i32 } }, ptr %a, i32 0, i32 1 + %a3 = getelementptr { i32, i32 }, ptr %a2, i32 0, i32 1 + ret ptr %a3 +} + +define ptr @geps_not_combinable(ptr %a) { +; CHECK-LABEL: @geps_not_combinable( +; CHECK-NEXT: [[A2:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 0, i32 1 +; CHECK-NEXT: [[A3:%.*]] = getelementptr { i32, i32 }, ptr [[A2]], i64 0, i32 1 +; CHECK-NEXT: ret ptr [[A3]] +; + %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1 + %a3 = getelementptr { i32, i32 }, ptr %a2, i32 0, i32 1 + ret ptr %a3 +}