1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2 ; RUN: opt < %s -S -passes=instcombine | FileCheck %s
4 declare void @use64(i64)
5 declare void @useptr(ptr)
7 define ptr @test_zero(ptr %base, i64 %a) {
8 ; CHECK-LABEL: define ptr @test_zero(
9 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
11 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]]
12 ; CHECK-NEXT: ret ptr [[P2]]
15 %p1 = getelementptr i8, ptr %base, i64 -4
16 %index = add i64 %a, 1
17 %p2 = getelementptr i32, ptr %p1, i64 %index
21 define ptr @test_nonzero(ptr %base, i64 %a) {
22 ; CHECK-LABEL: define ptr @test_nonzero(
23 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
25 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 4
26 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
27 ; CHECK-NEXT: ret ptr [[P2]]
30 %p1 = getelementptr i8, ptr %base, i64 -4
31 %index = add i64 %a, 2
32 %p2 = getelementptr i32, ptr %p1, i64 %index
36 define ptr @test_or_disjoint(ptr %base, i64 %a) {
37 ; CHECK-LABEL: define ptr @test_or_disjoint(
38 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
40 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]]
41 ; CHECK-NEXT: ret ptr [[P2]]
44 %p1 = getelementptr i8, ptr %base, i64 -4
45 %index = or disjoint i64 %a, 1
46 %p2 = getelementptr i32, ptr %p1, i64 %index
50 define ptr @test_zero_multiuse_index(ptr %base, i64 %a) {
51 ; CHECK-LABEL: define ptr @test_zero_multiuse_index(
52 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
54 ; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1
55 ; CHECK-NEXT: call void @use64(i64 [[INDEX]])
56 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]]
57 ; CHECK-NEXT: ret ptr [[P2]]
60 %p1 = getelementptr i8, ptr %base, i64 -4
61 %index = add i64 %a, 1
62 call void @use64(i64 %index)
63 %p2 = getelementptr i32, ptr %p1, i64 %index
67 define ptr @test_zero_multiuse_ptr(ptr %base, i64 %a) {
68 ; CHECK-LABEL: define ptr @test_zero_multiuse_ptr(
69 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
71 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
72 ; CHECK-NEXT: call void @useptr(ptr [[P1]])
73 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]]
74 ; CHECK-NEXT: ret ptr [[P2]]
77 %p1 = getelementptr i8, ptr %base, i64 -4
78 call void @useptr(ptr %p1)
79 %index = add i64 %a, 1
80 %p2 = getelementptr i32, ptr %p1, i64 %index
84 define ptr @test_zero_sext_add_nsw(ptr %base, i32 %a) {
85 ; CHECK-LABEL: define ptr @test_zero_sext_add_nsw(
86 ; CHECK-SAME: ptr [[BASE:%.*]], i32 [[A:%.*]]) {
88 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
89 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[A]] to i64
90 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[P1]], i64 [[TMP0]]
91 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4
92 ; CHECK-NEXT: ret ptr [[P2]]
95 %p1 = getelementptr i8, ptr %base, i64 -4
96 %index = add nsw i32 %a, 1
97 %p2 = getelementptr i32, ptr %p1, i32 %index
101 define ptr @test_zero_trunc_add(ptr %base, i128 %a) {
102 ; CHECK-LABEL: define ptr @test_zero_trunc_add(
103 ; CHECK-SAME: ptr [[BASE:%.*]], i128 [[A:%.*]]) {
105 ; CHECK-NEXT: [[TMP0:%.*]] = trunc i128 [[A]] to i64
106 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[TMP0]]
107 ; CHECK-NEXT: ret ptr [[P2]]
110 %p1 = getelementptr i8, ptr %base, i64 -4
111 %index = add i128 %a, 1
112 %p2 = getelementptr i32, ptr %p1, i128 %index
116 define ptr @test_non_i8(ptr %base, i64 %a) {
117 ; CHECK-LABEL: define ptr @test_non_i8(
118 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
120 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
121 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]]
122 ; CHECK-NEXT: ret ptr [[TMP0]]
125 %p1 = getelementptr i16, ptr %base, i64 -4
126 %index = add i64 %a, 1
127 %p2 = getelementptr i32, ptr %p1, i64 %index
131 define ptr @test_non_const(ptr %base, i64 %a, i64 %b) {
132 ; CHECK-LABEL: define ptr @test_non_const(
133 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
135 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[B]]
136 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]]
137 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 4
138 ; CHECK-NEXT: ret ptr [[P2]]
141 %p1 = getelementptr i8, ptr %base, i64 %b
142 %index = add i64 %a, 1
143 %p2 = getelementptr i32, ptr %p1, i64 %index
147 define ptr @test_too_many_indices(ptr %base, i64 %a, i64 %b) {
148 ; CHECK-LABEL: define ptr @test_too_many_indices(
149 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
151 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[B]]
152 ; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1
153 ; CHECK-NEXT: [[P2:%.*]] = getelementptr [8 x i32], ptr [[P1]], i64 1, i64 [[INDEX]]
154 ; CHECK-NEXT: ret ptr [[P2]]
157 %p1 = getelementptr i8, ptr %base, i64 %b
158 %index = add i64 %a, 1
159 %p2 = getelementptr [8 x i32], ptr %p1, i64 1, i64 %index
163 define ptr @test_wrong_op(ptr %base, i64 %a) {
164 ; CHECK-LABEL: define ptr @test_wrong_op(
165 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
167 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
168 ; CHECK-NEXT: [[INDEX:%.*]] = xor i64 [[A]], 1
169 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[INDEX]]
170 ; CHECK-NEXT: ret ptr [[P2]]
173 %p1 = getelementptr i8, ptr %base, i64 -4
174 %index = xor i64 %a, 1
175 %p2 = getelementptr i32, ptr %p1, i64 %index
179 define ptr @test_sext_add_without_nsw(ptr %base, i32 %a) {
180 ; CHECK-LABEL: define ptr @test_sext_add_without_nsw(
181 ; CHECK-SAME: ptr [[BASE:%.*]], i32 [[A:%.*]]) {
183 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
184 ; CHECK-NEXT: [[INDEX:%.*]] = add i32 [[A]], 1
185 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INDEX]] to i64
186 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[TMP0]]
187 ; CHECK-NEXT: ret ptr [[P2]]
190 %p1 = getelementptr i8, ptr %base, i64 -4
191 %index = add i32 %a, 1
192 %p2 = getelementptr i32, ptr %p1, i32 %index
196 define ptr @test_or_without_disjoint(ptr %base, i64 %a) {
197 ; CHECK-LABEL: define ptr @test_or_without_disjoint(
198 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
200 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
201 ; CHECK-NEXT: [[INDEX:%.*]] = or i64 [[A]], 1
202 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[INDEX]]
203 ; CHECK-NEXT: ret ptr [[P2]]
206 %p1 = getelementptr i8, ptr %base, i64 -4
207 %index = or i64 %a, 1
208 %p2 = getelementptr i32, ptr %p1, i64 %index
212 define ptr @test_smul_overflow(ptr %base, i64 %a) {
213 ; CHECK-LABEL: define ptr @test_smul_overflow(
214 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
216 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -12
217 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]]
218 ; CHECK-NEXT: ret ptr [[TMP0]]
221 %p1 = getelementptr i8, ptr %base, i64 -4
222 %index = add i64 %a, 9223372036854775806
223 %p2 = getelementptr i32, ptr %p1, i64 %index
227 define ptr @test_sadd_overflow(ptr %base, i64 %a) {
228 ; CHECK-LABEL: define ptr @test_sadd_overflow(
229 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
231 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -9223372036854775808
232 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]]
233 ; CHECK-NEXT: ret ptr [[TMP0]]
236 %p1 = getelementptr i8, ptr %base, i64 9223372036854775804
237 %index = add i64 %a, 1
238 %p2 = getelementptr i32, ptr %p1, i64 %index
242 define ptr @test_nonzero_multiuse_index(ptr %base, i64 %a) {
243 ; CHECK-LABEL: define ptr @test_nonzero_multiuse_index(
244 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
246 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
247 ; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 2
248 ; CHECK-NEXT: call void @use64(i64 [[INDEX]])
249 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[INDEX]]
250 ; CHECK-NEXT: ret ptr [[P2]]
253 %p1 = getelementptr i8, ptr %base, i64 -4
254 %index = add i64 %a, 2
255 call void @use64(i64 %index)
256 %p2 = getelementptr i32, ptr %p1, i64 %index
260 define ptr @test_nonzero_multiuse_ptr(ptr %base, i64 %a) {
261 ; CHECK-LABEL: define ptr @test_nonzero_multiuse_ptr(
262 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
264 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
265 ; CHECK-NEXT: call void @useptr(ptr [[P1]])
266 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]]
267 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 8
268 ; CHECK-NEXT: ret ptr [[P2]]
271 %p1 = getelementptr i8, ptr %base, i64 -4
272 call void @useptr(ptr %p1)
273 %index = add i64 %a, 2
274 %p2 = getelementptr i32, ptr %p1, i64 %index
278 define ptr @test_scalable(ptr %base, i64 %a) {
279 ; CHECK-LABEL: define ptr @test_scalable(
280 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
282 ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
283 ; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1
284 ; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
285 ; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 4
286 ; CHECK-NEXT: [[P2_IDX:%.*]] = mul i64 [[INDEX]], [[TMP1]]
287 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P1]], i64 [[P2_IDX]]
288 ; CHECK-NEXT: ret ptr [[P2]]
291 %p1 = getelementptr i8, ptr %base, i64 -4
292 %index = add i64 %a, 1
293 %p2 = getelementptr <vscale x 4 x i32>, ptr %p1, i64 %index