Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / gep-merge-constant-indices.ll
blobbcba8eadb1f966bc45877c062b7f250d4b942e4e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Test merging GEP of GEP with constant indices.
6 target datalayout = "i24:8:8"
8 %struct.A = type { [123 x i8], i32 }
9 %struct.B = type { i8, [3 x i16], %struct.A, float }
10 %struct.C = type { i8, i32, i32 }
12 ; result = (ptr) p + 3
13 define ptr @mergeBasic(ptr %p) {
14 ; CHECK-LABEL: @mergeBasic(
15 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 3
16 ; CHECK-NEXT:    ret ptr [[TMP1]]
18   %1 = getelementptr inbounds i32, ptr %p, i64 1
19   %2 = getelementptr inbounds i32, ptr %1, i64 2
20   ret ptr %2
23 ; Converted to ptr and merged.
24 ; result = (ptr) p + 10
25 define ptr @mergeDifferentTypes(ptr %p) {
26 ; CHECK-LABEL: @mergeDifferentTypes(
27 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 10
28 ; CHECK-NEXT:    ret ptr [[TMP1]]
30   %1 = getelementptr inbounds i8, ptr %p, i64 2
31   %2 = getelementptr inbounds i64, ptr %1, i64 1
32   ret ptr %2
35 ; Converted to ptr and merged.
36 ; result = (ptr) p + 10
37 define ptr @mergeReverse(ptr %p) {
38 ; CHECK-LABEL: @mergeReverse(
39 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 10
40 ; CHECK-NEXT:    ret ptr [[TMP1]]
42   %1 = getelementptr inbounds i64, ptr %p, i64 1
43   %2 = getelementptr inbounds i8, ptr %1, i64 2
44   ret ptr %2
47 ; Offsets of first and last GEP cancel out.
48 ; result = p
49 define ptr @zeroSum(ptr %p) {
50 ; CHECK-LABEL: @zeroSum(
51 ; CHECK-NEXT:    ret ptr [[P:%.*]]
53   %1 = getelementptr inbounds i32, ptr %p, i64 1
54   %2 = getelementptr inbounds i8, ptr %1, i64 -4
55   ret ptr %2
58 ; result = (ptr) ((ptr) p + 1) + 17
59 define ptr @array1(ptr %p) {
60 ; CHECK-LABEL: @array1(
61 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [20 x i8], ptr [[P:%.*]], i64 1, i64 17
62 ; CHECK-NEXT:    ret ptr [[TMP1]]
64   %1 = getelementptr inbounds [20 x i8], ptr %p, i64 1, i64 1
65   %2 = getelementptr inbounds i64, ptr %1, i64 2
66   ret ptr %2
69 ; Converted to ptr and merged.
70 ; result = (ptr) p + 20
71 define ptr @array2(ptr %p) {
72 ; CHECK-LABEL: @array2(
73 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 20
74 ; CHECK-NEXT:    ret ptr [[TMP1]]
76   %1 = getelementptr inbounds i64, ptr %p, i64 2
77   %2 = getelementptr inbounds [3 x i8], ptr %1, i64 1, i64 1
78   ret ptr %2
81 ; Converted to ptr and merged.
82 ; result = (ptr) p + 36
83 define ptr @struct1(ptr %p) {
84 ; CHECK-LABEL: @struct1(
85 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 36
86 ; CHECK-NEXT:    ret ptr [[TMP1]]
88   %1 = getelementptr inbounds i64, ptr %p, i64 3
89   %2 = getelementptr inbounds %struct.C, ptr %1, i64 1
90   ret ptr %2
93 ; result = &((struct.A*) p - 1).member1
94 define ptr @struct2(ptr %p) {
95 ; CHECK-LABEL: @struct2(
96 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[P:%.*]], i64 -1, i32 1
97 ; CHECK-NEXT:    ret ptr [[TMP1]]
99   %1 = getelementptr inbounds %struct.A, ptr %p, i64 0, i32 1
100   %2 = getelementptr inbounds i8, ptr %1, i64 -128
101   ret ptr %2
104 ; result = (ptr) &((struct.B) p)[0].member2.member0 + 7
105 define ptr @structStruct(ptr %p) {
106 ; CHECK-LABEL: @structStruct(
107 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[P:%.*]], i64 0, i32 2, i32 0, i64 7
108 ; CHECK-NEXT:    ret ptr [[TMP1]]
110   %1 = getelementptr inbounds %struct.B, ptr %p, i64 0, i32 2, i32 0, i64 3
111   %2 = getelementptr inbounds %struct.A, ptr %1, i64 0, i32 0, i64 4
112   ret ptr %2
115 ; First GEP offset is not divisible by last GEP's source element size, but first
116 ; GEP points to an array such that the last GEP offset is divisible by the
117 ; array's element size, so the first GEP can be rewritten with an extra index.
118 ; result = (ptr) &((struct.B*) p)[i].member1 + 2
119 define ptr @appendIndex(ptr %p, i64 %i) {
120 ; CHECK-LABEL: @appendIndex(
121 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[P:%.*]], i64 [[I:%.*]], i32 1, i64 2
122 ; CHECK-NEXT:    ret ptr [[TMP1]]
124   %1 = getelementptr inbounds %struct.B, ptr %p, i64 %i, i32 1
125   %2 = getelementptr inbounds i32, ptr %1, i64 1
126   ret ptr %2
129 ; Offset of either GEP is not divisible by the other's size, converted to ptr
130 ; and merged.
131 ; Here i24 is 8-bit aligned.
132 ; result = (ptr) p + 7
133 define ptr @notDivisible(ptr %p) {
134 ; CHECK-LABEL: @notDivisible(
135 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 7
136 ; CHECK-NEXT:    ret ptr [[TMP1]]
138   %1 = getelementptr inbounds i24, ptr %p, i64 1
139   %2 = getelementptr inbounds i32, ptr %1, i64 1
140   ret ptr %2
143 ; Negative test. Two GEP should not be merged if not both offsets are constant
144 ; or divisible by the other's size.
145 define ptr @partialConstant2(ptr %p, i64 %a) {
146 ; CHECK-LABEL: @partialConstant2(
147 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
148 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [4 x i64], ptr [[TMP1]], i64 [[A:%.*]], i64 2
149 ; CHECK-NEXT:    ret ptr [[TMP2]]
151   %1 = getelementptr inbounds i32, ptr %p, i64 1
152   %2 = getelementptr inbounds [4 x i64], ptr %1, i64 %a, i64 2
153   ret ptr %2
156 ; Negative test. Two GEP should not be merged if there is another use of the
157 ; first GEP by the second GEP.
158 define ptr @partialConstant3(ptr %p) {
159 ; CHECK-LABEL: @partialConstant3(
160 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
161 ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
162 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [4 x i64], ptr [[TMP1]], i64 [[TMP2]], i64 2
163 ; CHECK-NEXT:    ret ptr [[TMP3]]
165   %1 = getelementptr inbounds i32, ptr %p, i64 1
166   %2 = ptrtoint ptr %1 to i64
167   %3 = getelementptr inbounds [4 x i64], ptr %1, i64 %2, i64 2
168   ret ptr %3
171 ; Two GEP instructions can be merged if one is constant-indexed and the other
172 ; is an aggregate type with a constant last index, and the resulting pointer
173 ; address by adding the constant offset aliases the address of another member.
174 ; result = &((struct.C*) p + a).member2
175 define ptr @partialConstantMemberAliasing1(ptr %p, i64 %a) {
176 ; CHECK-LABEL: @partialConstantMemberAliasing1(
177 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]], i32 2
178 ; CHECK-NEXT:    ret ptr [[TMP1]]
180   %1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1
181   %2 = getelementptr inbounds i32, ptr %1, i64 1
182   ret ptr %2
185 ; Negative test. Similar to above, but the new address does not alias the
186 ; address of another member.
187 define ptr @partialConstantMemberAliasing2(ptr %p, i64 %a) {
188 ; CHECK-LABEL: @partialConstantMemberAliasing2(
189 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]], i32 1
190 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 1
191 ; CHECK-NEXT:    ret ptr [[TMP2]]
193   %1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1
194   %2 = getelementptr inbounds i8, ptr %1, i64 1
195   ret ptr %2
198 ; Negative test. Similar to above, but the new address falls outside the address
199 ; range of the object currently pointed by the non-constant GEP.
200 define ptr @partialConstantMemberAliasing3(ptr %p, i64 %a) {
201 ; CHECK-LABEL: @partialConstantMemberAliasing3(
202 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]], i32 2
203 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
204 ; CHECK-NEXT:    ret ptr [[TMP2]]
206   %1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 2
207   %2 = getelementptr inbounds i32, ptr %1, i64 1
208   ret ptr %2