Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1553,27 +1553,21 @@ // Replace: gep (gep %P, long B), long A, ... // With: T = long A+B; gep %P, T, ... // - Value *Sum; Value *SO1 = Src->getOperand(Src->getNumOperands()-1); Value *GO1 = GEP.getOperand(1); - if (SO1 == Constant::getNullValue(SO1->getType())) { - Sum = GO1; - } else if (GO1 == Constant::getNullValue(GO1->getType())) { - Sum = SO1; - } else { - // If they aren't the same type, then the input hasn't been processed - // by the loop above yet (which canonicalizes sequential index types to - // intptr_t). Just avoid transforming this until the input has been - // normalized. - if (SO1->getType() != GO1->getType()) - return nullptr; - // Only do the combine when GO1 and SO1 are both constants. Only in - // this case, we are sure the cost after the merge is never more than - // that before the merge. - if (!isa(GO1) || !isa(SO1)) - return nullptr; - Sum = Builder->CreateAdd(SO1, GO1, PtrOp->getName()+".sum"); - } + + // If they aren't the same type, then the input hasn't been processed + // by the loop above yet (which canonicalizes sequential index types to + // intptr_t). Just avoid transforming this until the input has been + // normalized. + if (SO1->getType() != GO1->getType()) + return nullptr; + + Value* Sum = SimplifyAddInst(GO1, SO1, false, false, DL, &TLI, &DT, &AC); + // Only do the combine when we are sure the cost after the + // merge is never more than that before the merge. + if (Sum == nullptr) + return nullptr; // Update the GEP in place if possible. if (Src->getNumOperands() == 2) { Index: test/Transforms/InstCombine/getelementptr.ll =================================================================== --- test/Transforms/InstCombine/getelementptr.ll +++ test/Transforms/InstCombine/getelementptr.ll @@ -883,6 +883,33 @@ ; CHECK-NEXT: ret %struct.C* [[GEP]] } +define i32* @test47(i32* %I, i64 %C, i64 %D) { + %sub = sub i64 %D, %C + %A = getelementptr i32, i32* %I, i64 %C + %B = getelementptr i32, i32* %A, i64 %sub + ret i32* %B +; CHECK-LABEL: @test47( +; CHECK-NEXT: %B = getelementptr i32, i32* %I, i64 %D +} + +define i32* @test48(i32* %I, i64 %C, i64 %D) { + %sub = sub i64 %D, %C + %A = getelementptr i32, i32* %I, i64 %sub + %B = getelementptr i32, i32* %A, i64 %C + ret i32* %B +; CHECK-LABEL: @test48( +; CHECK-NEXT: %B = getelementptr i32, i32* %I, i64 %D +} + +define i32* @test49(i32* %I, i64 %C) { + %notC = xor i64 -1, %C + %A = getelementptr i32, i32* %I, i64 %C + %B = getelementptr i32, i32* %A, i64 %notC + ret i32* %B +; CHECK-LABEL: @test49( +; CHECK-NEXT: %B = getelementptr i32, i32* %I, i64 -1 +} + define i32 addrspace(1)* @ascast_0_gep(i32* %p) nounwind { ; CHECK-LABEL: @ascast_0_gep( ; CHECK-NOT: getelementptr