| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | 
 | ; RUN: opt < %s -passes=instcombine -S | FileCheck %s | 
 |  | 
 | ; Constant-indexed GEP instructions in a chain of GEP instructions should be | 
 | ; swapped to the end whenever such transformation is valid. This allows them to | 
 | ; be merged. | 
 |  | 
 | declare void @use(i1) | 
 |  | 
 |  | 
 | ; The constant-indexed GEP instruction should be swapped to the end, even | 
 | ; without merging. | 
 | ; result = (((ptr) p + a) + b) + 1 | 
 | define ptr @basic(ptr %p, i64 %a, i64 %b) { | 
 | ; CHECK-LABEL: @basic( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[A:%.*]] | 
 | ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 [[B:%.*]] | 
 | ; CHECK-NEXT:    ret ptr [[TMP3]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %p, i64 1 | 
 |   %2 = getelementptr inbounds i32, ptr %1, i64 %a | 
 |   %3 = getelementptr inbounds i32, ptr %2, i64 %b | 
 |   ret ptr %3 | 
 | } | 
 |  | 
 | ; GEP with the last index being a constant should also be swapped. | 
 | define ptr @partialConstant1(ptr %p, i64 %a, i64 %b) { | 
 | ; CHECK-LABEL: @partialConstant1( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[B:%.*]] | 
 | ; CHECK-NEXT:    ret ptr [[TMP1]] | 
 | ; | 
 |   %1 = getelementptr inbounds [4 x i32], ptr %p, i64 %a, i64 1 | 
 |   %2 = getelementptr inbounds i32, ptr %p, i64 %b | 
 |   ret ptr %2 | 
 | } | 
 |  | 
 | ; Negative test. GEP should not be swapped if the last index is not a constant. | 
 | define ptr @partialConstant2(ptr %p, i64 %a, i64 %b) { | 
 | ; CHECK-LABEL: @partialConstant2( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[B:%.*]] | 
 | ; CHECK-NEXT:    ret ptr [[TMP1]] | 
 | ; | 
 |   %1 = getelementptr inbounds [4 x i32], ptr %p, i64 1, i64 %a | 
 |   %2 = getelementptr inbounds i32, ptr %p, i64 %b | 
 |   ret ptr %2 | 
 | } | 
 |  | 
 | ; Constant-indexed GEP are merged after swawpping. | 
 | ; result = ((ptr) p + a) + 3 | 
 | define ptr @merge(ptr %p, i64 %a) { | 
 | ; CHECK-LABEL: @merge( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[A:%.*]] | 
 | ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2 | 
 | ; CHECK-NEXT:    ret ptr [[TMP3]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %p, i64 1 | 
 |   %2 = getelementptr inbounds i32, ptr %1, i64 %a | 
 |   %3 = getelementptr inbounds i32, ptr %2, i64 2 | 
 |   ret ptr %3 | 
 | } | 
 |  | 
 | ; Multiple constant-indexed GEP. Note that the first two cannot be merged at | 
 | ; first, but after the second and third are merged, the result can be merged | 
 | ; with the first one on the next pass. | 
 | ; result = (ptr) ((ptr) ((ptr) ptr + a) + (a * b)) + 9 | 
 | define ptr @nested(ptr %p, i64 %a, i64 %b) { | 
 | ; CHECK-LABEL: @nested( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <3 x i32>, ptr [[P:%.*]], i64 1 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 [[A:%.*]] | 
 | ; CHECK-NEXT:    [[TMP3:%.*]] = mul i64 [[A]], [[B:%.*]] | 
 | ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds <5 x i32>, ptr [[TMP2]], i64 4 | 
 | ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[TMP4]], i64 [[TMP3]] | 
 | ; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, ptr [[TMP5]], i64 1 | 
 | ; CHECK-NEXT:    ret ptr [[TMP6]] | 
 | ; | 
 |   %1 = getelementptr inbounds <3 x i32>, ptr %p, i64 1 | 
 |   %2 = getelementptr inbounds i8, ptr %1, i64 %a | 
 |   %3 = mul i64 %a, %b | 
 |   %4 = getelementptr inbounds <5 x i32>, ptr %2, i64 4 | 
 |   %5 = getelementptr inbounds i16, ptr %4, i64 %3 | 
 |   %6 = getelementptr inbounds <4 x i32>, ptr %5, i64 1 | 
 |   ret ptr %6 | 
 | } | 
 |  | 
 | ; It is valid to swap if the source operand of the first GEP has multiple uses. | 
 | define ptr @multipleUses1(ptr %p) { | 
 | ; CHECK-LABEL: @multipleUses1( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[P]] to i64 | 
 | ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[TMP2]] | 
 | ; CHECK-NEXT:    ret ptr [[TMP3]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %p, i64 1 | 
 |   %2 = ptrtoint ptr %p to i64 | 
 |   %3 = getelementptr inbounds i32, ptr %1, i64 %2 | 
 |   ret ptr %3 | 
 | } | 
 |  | 
 | ; It is valid to swap if the second GEP has multiple uses. | 
 | define ptr @multipleUses2(ptr %p, i64 %a) { | 
 | ; CHECK-LABEL: @multipleUses2( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[A:%.*]] | 
 | ; CHECK-NEXT:    call void @use(ptr nonnull [[TMP2]]) | 
 | ; CHECK-NEXT:    ret ptr [[TMP2]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %p, i64 1 | 
 |   %2 = getelementptr inbounds i32, ptr %1, i64 %a | 
 |   call void @use(ptr %2) | 
 |   ret ptr %2 | 
 | } | 
 |  | 
 | ; Negative test. It is not valid to swap if the first GEP has multiple uses. | 
 | define ptr @multipleUses3(ptr %p) { | 
 | ; CHECK-LABEL: @multipleUses3( | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 | 
 | ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[TMP2]] | 
 | ; CHECK-NEXT:    ret ptr [[TMP3]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %p, i64 1 | 
 |   %2 = ptrtoint ptr %1 to i64 | 
 |   %3 = getelementptr inbounds i32, ptr %1, i64 %2 | 
 |   ret ptr %3 | 
 | } |