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 @@ -2024,24 +2024,13 @@ } } - // Handle malformed GEP of GEP in PR13621, where Src and GEP mutually use each - // other. This is normally not allowed, so just bail out. - if (llvm::any_of(GEP.users(), [&](User *U) { - if (Instruction *SrcI = dyn_cast(Src)) { - return U == SrcI || DT.dominates(U, SrcI); - } - return false; - })) - return nullptr; - // Canonicalize swapping. Swap GEP with constant index suffix to the back if // it doesn't violate def-use relations or contradict with loop invariant // swap above. This allows more potential applications of constant-indexed GEP // optimizations below. if (shouldCanonicalizeSwap && Src->hasOneUse() && - (Src->getType()->getScalarType()->isOpaquePointerTy() || - Src->getPointerOperand()->getType() == - GEP.getPointerOperand()->getType())) { + Src->getPointerOperand()->getType() == + GEP.getPointerOperand()->getType()) { // When swapping, GEP with all constant indices are more prioritized than // GEP with only the last few indices (but not all) being constant because // it may be merged with GEP with all constant indices. @@ -2051,9 +2040,7 @@ bool InBounds = isMergedGEPInBounds(*Src, *cast(&GEP)); Value *NewSrc = Builder.CreateGEP( GEP.getSourceElementType(), Src->getOperand(0), - SmallVector(GEP.indices()), Src->getName()); - if (GetElementPtrInst *NewGEP = dyn_cast(NewSrc)) - NewGEP->setIsInBounds(InBounds); + SmallVector(GEP.indices()), Src->getName(), InBounds); GetElementPtrInst *NewGEP = GetElementPtrInst::Create( Src->getSourceElementType(), NewSrc, SmallVector(Src->indices()), GEP.getName()); @@ -2100,23 +2087,11 @@ 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 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()); + if (!Offset.isZero() || (!IsFirstType && !ConstIndices[0].isZero())) 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,8 +56,9 @@ ; result = (i8*) p + 14 define ptr @array2(ptr %p, i64 %a) { ; CHECK-LABEL: @array2( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 14 -; CHECK-NEXT: ret ptr [[TMP1]] +; 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]] ; %1 = getelementptr inbounds [7 x i32], ptr %p, i64 0, i64 3 %2 = getelementptr inbounds i8, ptr %1, i64 2 @@ -67,8 +68,9 @@ ; result = (i8*) p + 20 define ptr @array3(ptr %p) { ; CHECK-LABEL: @array3( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 20 -; CHECK-NEXT: ret ptr [[TMP1]] +; 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]] ; %1 = getelementptr inbounds i64, ptr %p, i64 2 %2 = getelementptr inbounds [3 x i8], ptr %1, i64 1, i64 1 @@ -78,8 +80,9 @@ ; result = (i8*) p + 36 define ptr @struct1(ptr %p) { ; CHECK-LABEL: @struct1( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 36 -; CHECK-NEXT: ret ptr [[TMP1]] +; 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]] ; %1 = getelementptr inbounds i64, ptr %p, i64 3 %2 = getelementptr inbounds %struct.C, ptr %1, i64 1 @@ -138,8 +141,9 @@ ; result = &((struct.C*) p + 2).member1 define ptr @structMemberAliasing(ptr %p, i64 %a) { ; CHECK-LABEL: @structMemberAliasing( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 28 -; CHECK-NEXT: ret ptr [[TMP1]] +; 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]] ; %1 = getelementptr inbounds i64, ptr %p, i64 1 %2 = getelementptr inbounds %struct.C, ptr %1, i64 1, i32 2 @@ -150,8 +154,9 @@ ; 8-bit aligned. define ptr @notDivisible(ptr %p) { ; CHECK-LABEL: @notDivisible( -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 7 -; CHECK-NEXT: ret ptr [[TMP1]] +; 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]] ; %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,7 +211,8 @@ define ptr @geps_combinable_different_elem_type4(ptr %a) { ; CHECK-LABEL: @geps_combinable_different_elem_type4( -; CHECK-NEXT: [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 14 +; CHECK-NEXT: [[A2:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 0, i32 1 +; CHECK-NEXT: [[A3:%.*]] = getelementptr i8, ptr [[A2]], i64 10 ; CHECK-NEXT: ret ptr [[A3]] ; %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1