Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1544,6 +1544,28 @@ if (!shouldMergeGEPs(*cast(&GEP), *Src)) return nullptr; + SmallVector Indices; + + auto createGEPWithIndices = [&]() { + return GEP.isInBounds() && Src->isInBounds() + ? GetElementPtrInst::CreateInBounds( + Src->getSourceElementType(), Src->getOperand(0), Indices, + GEP.getName()) + : GetElementPtrInst::Create(Src->getSourceElementType(), + Src->getOperand(0), Indices, + GEP.getName()); + }; + + // Fold Src into GEP if the first index of GEP is zero. We perform this + // simplification regardless of whether Src is also in a GEP chain. + if (isa(*GEP.idx_begin()) && + cast(*GEP.idx_begin())->isNullValue() && + Src->getNumOperands() != 1) { + Indices.append(Src->op_begin() + 1, Src->op_end()); + Indices.append(GEP.idx_begin() + 1, GEP.idx_end()); + return createGEPWithIndices(); + } + // Note that if our source is a gep chain itself then we wait for that // chain to be resolved before we perform this transformation. This // avoids us creating a TON of code in some cases. @@ -1552,8 +1574,6 @@ if (SrcGEP->getNumOperands() == 2 && shouldMergeGEPs(*Src, *SrcGEP)) return nullptr; // Wait until our source is folded to completion. - SmallVector Indices; - // Find out whether the last index in the source GEP is a sequential idx. bool EndsWithSequential = false; for (gep_type_iterator I = gep_type_begin(*Src), E = gep_type_end(*Src); @@ -1590,22 +1610,8 @@ Indices.append(Src->op_begin()+1, Src->op_end()-1); Indices.push_back(Sum); Indices.append(GEP.op_begin()+2, GEP.op_end()); - } else if (isa(*GEP.idx_begin()) && - cast(*GEP.idx_begin())->isNullValue() && - Src->getNumOperands() != 1) { - // Otherwise we can do the fold if the first index of the GEP is a zero - Indices.append(Src->op_begin()+1, Src->op_end()); - Indices.append(GEP.idx_begin()+1, GEP.idx_end()); + return createGEPWithIndices(); } - - if (!Indices.empty()) - return GEP.isInBounds() && Src->isInBounds() - ? GetElementPtrInst::CreateInBounds( - Src->getSourceElementType(), Src->getOperand(0), Indices, - GEP.getName()) - : GetElementPtrInst::Create(Src->getSourceElementType(), - Src->getOperand(0), Indices, - GEP.getName()); } if (GEP.getNumIndices() == 1) { Index: test/Transforms/InstCombine/getelementptr.ll =================================================================== --- test/Transforms/InstCombine/getelementptr.ll +++ test/Transforms/InstCombine/getelementptr.ll @@ -931,4 +931,16 @@ ret i32 addrspace(1)* %x } +define i32* @resolve_gep_chains(%pair* %p, i64 %i) { +; CHECK-LABEL: @resolve_gep_chains( +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr %pair, %pair* %p, i64 %i +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr %pair, %pair* [[TMP0]], i64 1, i32 1 +; CHECK-NEXT: ret i32* [[TMP2]] +; + %tmp0 = getelementptr %pair, %pair* %p, i64 %i + %tmp1 = getelementptr %pair, %pair* %tmp0, i64 1 + %tmp2 = getelementptr %pair, %pair* %tmp1, i64 0, i32 1 + ret i32* %tmp2 +} + ; CHECK: attributes [[NUW]] = { nounwind }