Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1348,6 +1348,11 @@ // normalized. if (SO1->getType() != GO1->getType()) return nullptr; + + // Is it worth summing the offsets? + if (!isa(SO1)) + return nullptr; + Sum = Builder->CreateAdd(SO1, GO1, PtrOp->getName()+".sum"); } Index: test/Transforms/InstCombine/getelementptr.ll =================================================================== --- test/Transforms/InstCombine/getelementptr.ll +++ test/Transforms/InstCombine/getelementptr.ll @@ -98,15 +98,44 @@ ret void } +; Ensure we don't canonicalize chains of GEPs with many unknowns into arithmetic define i32* @test7(i32* %I, i64 %C, i64 %D) { %A = getelementptr i32* %I, i64 %C %B = getelementptr i32* %A, i64 %D ret i32* %B ; CHECK-LABEL: @test7( -; CHECK: %A.sum = add i64 %C, %D -; CHECK: getelementptr i32* %I, i64 %A.sum +; CHECK: getelementptr i32* %I, i64 %C +; CHECK: getelementptr i32* %A, i64 %D } +; Don't canonicalize away from (%stack - %offset) + idx form (#19973) +define i32 @test_gep_canon_1(i32* %stack, i64 %offset) { + %neg = sub i64 0, %offset + %base = getelementptr i32* %stack, i64 %neg + %1 = getelementptr i32* %base, i64 1 + %2 = getelementptr i32* %base, i64 2 + %A = load i32* %1 + %B = load i32* %2 + %ret = add i32 %A, %B + ret i32 %ret + ; CHECK-LABEL: @test_gep_canon_1( + ; CHECK: %neg = sub i64 0, %offset + ; CHECK-NEXT: getelementptr i32* %stack, i64 %neg + ; CHECK: getelementptr i32* %base, i64 1 + ; CHECK: getelementptr i32* %base, i64 2 +} + +; Fold constant offsets hidden in arithmetic +define i32* @test_gep_canon_2_add(i32* %A, i32 %B) { + %C = add i32 %B, 3 + %D = getelementptr i32* %A, i32 %C + %E = getelementptr i32* %D, i32 4 + ret i32* %E + ; CHECK-LABEL: @test_gep_canon_2_add( + ; CHECK: %D = getelementptr i32* %A, i32 %B + ; CHECK: getelementptr i32* %D, i32 7 +} + define i8* @test8([10 x i32]* %X) { ;; Fold into the cast. %A = getelementptr [10 x i32]* %X, i64 0, i64 0