xref: /llvm-project/llvm/test/Transforms/InstCombine/opaque-ptr.ll (revision a4d92400a6db9566d84cb4b900149e36e117f452)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes='instcombine<no-verify-fixpoint>' < %s | FileCheck %s
3
4; In the indexed_compare test the comparison is only converted int a form
5; from which we can infer non-negativity after the GEP has already been sunk
6; and revisited.
7
8define ptr @bitcast_opaque_to_opaque(ptr %a) {
9; CHECK-LABEL: @bitcast_opaque_to_opaque(
10; CHECK-NEXT:    ret ptr [[A:%.*]]
11;
12  ret ptr %a
13}
14
15define ptr @bitcast_typed_to_opaque(ptr %a) {
16; CHECK-LABEL: @bitcast_typed_to_opaque(
17; CHECK-NEXT:    ret ptr [[A:%.*]]
18;
19  ret ptr %a
20}
21
22define ptr @bitcast_opaque_to_typed(ptr %a) {
23; CHECK-LABEL: @bitcast_opaque_to_typed(
24; CHECK-NEXT:    ret ptr [[A:%.*]]
25;
26  ret ptr %a
27}
28
29@g = global i8 0
30define ptr @bitcast_typed_to_opaque_constexpr() {
31; CHECK-LABEL: @bitcast_typed_to_opaque_constexpr(
32; CHECK-NEXT:    ret ptr @g
33;
34  ret ptr @g
35}
36
37define ptr @addrspacecast_opaque_to_opaque(ptr addrspace(1) %a) {
38; CHECK-LABEL: @addrspacecast_opaque_to_opaque(
39; CHECK-NEXT:    [[B:%.*]] = addrspacecast ptr addrspace(1) [[A:%.*]] to ptr
40; CHECK-NEXT:    ret ptr [[B]]
41;
42  %b = addrspacecast ptr addrspace(1) %a to ptr
43  ret ptr %b
44}
45
46define ptr @addrspacecast_typed_to_opaque(ptr addrspace(1) %a) {
47; CHECK-LABEL: @addrspacecast_typed_to_opaque(
48; CHECK-NEXT:    [[B:%.*]] = addrspacecast ptr addrspace(1) [[A:%.*]] to ptr
49; CHECK-NEXT:    ret ptr [[B]]
50;
51  %b = addrspacecast ptr addrspace(1) %a to ptr
52  ret ptr %b
53}
54
55define ptr @addrspacecast_opaque_to_typed(ptr addrspace(1) %a) {
56; CHECK-LABEL: @addrspacecast_opaque_to_typed(
57; CHECK-NEXT:    [[B:%.*]] = addrspacecast ptr addrspace(1) [[A:%.*]] to ptr
58; CHECK-NEXT:    ret ptr [[B]]
59;
60  %b = addrspacecast ptr addrspace(1) %a to ptr
61  ret ptr %b
62}
63
64define ptr addrspace(1) @bitcast_and_addrspacecast_eliminable(ptr %a) {
65; CHECK-LABEL: @bitcast_and_addrspacecast_eliminable(
66; CHECK-NEXT:    [[C:%.*]] = addrspacecast ptr [[A:%.*]] to ptr addrspace(1)
67; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
68;
69  %c = addrspacecast ptr %a to ptr addrspace(1)
70  ret ptr addrspace(1) %c
71}
72
73define ptr addrspace(1) @addrspacecast_typed_to_opaque_constexpr() {
74; CHECK-LABEL: @addrspacecast_typed_to_opaque_constexpr(
75; CHECK-NEXT:    ret ptr addrspace(1) addrspacecast (ptr @g to ptr addrspace(1))
76;
77  ret ptr addrspace(1) addrspacecast (ptr @g to ptr addrspace(1))
78}
79
80define ptr @gep_constexpr_1(ptr %a) {
81; CHECK-LABEL: @gep_constexpr_1(
82; CHECK-NEXT:    ret ptr inttoptr (i64 6 to ptr)
83;
84  ret ptr getelementptr (i16, ptr null, i32 3)
85}
86
87define ptr @gep_constexpr_2(ptr %a) {
88; CHECK-LABEL: @gep_constexpr_2(
89; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g, i64 3)
90;
91  ret ptr getelementptr (i8, ptr @g, i32 3)
92}
93
94define ptr addrspace(1) @gep_constexpr_3(ptr %a) {
95; CHECK-LABEL: @gep_constexpr_3(
96; CHECK-NEXT:    ret ptr addrspace(1) getelementptr (i8, ptr addrspace(1) addrspacecast (ptr @g to ptr addrspace(1)), i64 3)
97;
98  ret ptr addrspace(1) getelementptr ([0 x i8], ptr addrspace(1) addrspacecast (ptr @g to ptr addrspace(1)), i64 0, i32 3)
99}
100
101define ptr @load_bitcast_1(ptr %a) {
102; CHECK-LABEL: @load_bitcast_1(
103; CHECK-NEXT:    [[B:%.*]] = load ptr, ptr [[A:%.*]], align 8
104; CHECK-NEXT:    ret ptr [[B]]
105;
106  %b = load ptr, ptr %a
107  ret ptr %b
108}
109
110define ptr @load_bitcast_2(ptr %a) {
111; CHECK-LABEL: @load_bitcast_2(
112; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[A:%.*]], align 8
113; CHECK-NEXT:    ret ptr [[C]]
114;
115  %c = load ptr, ptr %a
116  ret ptr %c
117}
118
119define void @call(ptr %a) {
120; CHECK-LABEL: @call(
121; CHECK-NEXT:    call void [[A:%.*]]()
122; CHECK-NEXT:    ret void
123;
124  call void %a()
125  ret void
126}
127
128declare void @varargs(...)
129define void @varargs_cast_typed_to_opaque_same_type(ptr %a) {
130; CHECK-LABEL: @varargs_cast_typed_to_opaque_same_type(
131; CHECK-NEXT:    call void (...) @varargs(ptr byval(i32) [[A:%.*]])
132; CHECK-NEXT:    ret void
133;
134  call void (...) @varargs(ptr byval(i32) %a)
135  ret void
136}
137
138define void @varargs_cast_typed_to_opaque_different_type(ptr %a) {
139; CHECK-LABEL: @varargs_cast_typed_to_opaque_different_type(
140; CHECK-NEXT:    call void (...) @varargs(ptr byval(float) [[A:%.*]])
141; CHECK-NEXT:    ret void
142;
143  call void (...) @varargs(ptr byval(float) %a)
144  ret void
145}
146
147define void @varargs_cast_typed_to_opaque_different_size(ptr %a) {
148; CHECK-LABEL: @varargs_cast_typed_to_opaque_different_size(
149; CHECK-NEXT:    call void (...) @varargs(ptr byval(i64) [[A:%.*]])
150; CHECK-NEXT:    ret void
151;
152  call void (...) @varargs(ptr byval(i64) %a)
153  ret void
154}
155
156define void @varargs_cast_opaque_to_typed(ptr %a) {
157; CHECK-LABEL: @varargs_cast_opaque_to_typed(
158; CHECK-NEXT:    call void (...) @varargs(ptr byval(i8) [[A:%.*]])
159; CHECK-NEXT:    ret void
160;
161  call void (...) @varargs(ptr byval(i8) %a)
162  ret void
163}
164
165define ptr @geps_combinable(ptr %a) {
166; CHECK-LABEL: @geps_combinable(
167; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8
168; CHECK-NEXT:    ret ptr [[A3]]
169;
170  %a2 = getelementptr { i32, { i32, i32 } }, ptr %a, i32 0, i32 1
171  %a3 = getelementptr { i32, i32 }, ptr %a2, i32 0, i32 1
172  ret ptr %a3
173}
174
175define ptr @geps_combinable_different_elem_type1(ptr %a) {
176; CHECK-LABEL: @geps_combinable_different_elem_type1(
177; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8
178; CHECK-NEXT:    ret ptr [[A3]]
179;
180  %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1
181  %a3 = getelementptr { i32, i32 }, ptr %a2, i32 0, i32 1
182  ret ptr %a3
183}
184
185define ptr @geps_combinable_different_elem_type2(ptr %a) {
186; CHECK-LABEL: @geps_combinable_different_elem_type2(
187; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8
188; CHECK-NEXT:    ret ptr [[A3]]
189;
190  %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1
191  %a3 = getelementptr i8, ptr %a2, i64 4
192  ret ptr %a3
193}
194
195define ptr @geps_combinable_different_elem_type3(ptr %a) {
196; CHECK-LABEL: @geps_combinable_different_elem_type3(
197; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 12
198; CHECK-NEXT:    ret ptr [[A3]]
199;
200  %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1
201  %a3 = getelementptr i8, ptr %a2, i64 8
202  ret ptr %a3
203}
204
205define ptr @geps_combinable_different_elem_type4(ptr %a) {
206; CHECK-LABEL: @geps_combinable_different_elem_type4(
207; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 14
208; CHECK-NEXT:    ret ptr [[A3]]
209;
210  %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1
211  %a3 = getelementptr i8, ptr %a2, i64 10
212  ret ptr %a3
213}
214
215define ptr @geps_combinable_different_elem_type5(ptr %a) {
216; CHECK-LABEL: @geps_combinable_different_elem_type5(
217; CHECK-NEXT:    ret ptr [[A:%.*]]
218;
219  %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1
220  %a3 = getelementptr i8, ptr %a2, i64 -4
221  ret ptr %a3
222}
223
224define ptr @geps_combinable_different_elem_type6(ptr %a, i64 %idx) {
225; CHECK-LABEL: @geps_combinable_different_elem_type6(
226; CHECK-NEXT:    [[A3:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[IDX:%.*]], i32 1
227; CHECK-NEXT:    ret ptr [[A3]]
228;
229  %a2 = getelementptr { i32, i32 }, ptr %a, i64 %idx
230  %a3 = getelementptr i8, ptr %a2, i64 4
231  ret ptr %a3
232}
233
234define ptr @geps_combinable_different_elem_type7(ptr %a, i64 %idx) {
235; CHECK-LABEL: @geps_combinable_different_elem_type7(
236; CHECK-NEXT:    [[A2:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[IDX:%.*]], i32 1
237; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A2]], i64 4
238; CHECK-NEXT:    ret ptr [[A3]]
239;
240  %a2 = getelementptr { i32, i32 }, ptr %a, i64 %idx, i32 1
241  %a3 = getelementptr i8, ptr %a2, i64 4
242  ret ptr %a3
243}
244
245define ptr @geps_combinable_different_elem_type8(ptr %a, i64 %idx) {
246; CHECK-LABEL: @geps_combinable_different_elem_type8(
247; CHECK-NEXT:    [[A2:%.*]] = getelementptr inbounds { { i32, i32 } }, ptr [[A:%.*]], i64 [[IDX:%.*]], i32 0, i32 1
248; CHECK-NEXT:    [[A3:%.*]] = getelementptr inbounds nuw i8, ptr [[A2]], i64 4
249; CHECK-NEXT:    ret ptr [[A3]]
250;
251  %a2 = getelementptr inbounds { { i32, i32 } }, ptr %a, i64 %idx, i32 0, i32 1
252  %a3 = getelementptr inbounds i8, ptr %a2, i32 4
253  ret ptr %a3
254}
255
256define ptr @geps_combinable_different_elem_type9(ptr %a, i64 %idx) {
257; CHECK-LABEL: @geps_combinable_different_elem_type9(
258; CHECK-NEXT:    [[A3:%.*]] = getelementptr inbounds { { i32, i32 } }, ptr [[A:%.*]], i64 [[IDX:%.*]]
259; CHECK-NEXT:    ret ptr [[A3]]
260;
261  %a2 = getelementptr inbounds { { i32, i32 } }, ptr %a, i64 %idx, i32 0, i32 1
262  %a3 = getelementptr inbounds i8, ptr %a2, i32 -4
263  ret ptr %a3
264}
265
266declare void @use(ptr)
267
268define ptr @geps_combinable_different_elem_type_extra_use1(ptr %a) {
269; CHECK-LABEL: @geps_combinable_different_elem_type_extra_use1(
270; CHECK-NEXT:    [[A2:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 4
271; CHECK-NEXT:    call void @use(ptr [[A2]])
272; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A]], i64 8
273; CHECK-NEXT:    ret ptr [[A3]]
274;
275  %a2 = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1
276  call void @use(ptr %a2)
277  %a3 = getelementptr i8, ptr %a2, i64 4
278  ret ptr %a3
279}
280
281define ptr @geps_combinable_different_elem_type_extra_use2(ptr %a, i64 %idx) {
282; CHECK-LABEL: @geps_combinable_different_elem_type_extra_use2(
283; CHECK-NEXT:    [[A2:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[IDX:%.*]]
284; CHECK-NEXT:    call void @use(ptr [[A2]])
285; CHECK-NEXT:    [[A3:%.*]] = getelementptr i8, ptr [[A2]], i64 4
286; CHECK-NEXT:    ret ptr [[A3]]
287;
288  %a2 = getelementptr { i32, i32 }, ptr %a, i64 %idx
289  call void @use(ptr %a2)
290  %a3 = getelementptr i8, ptr %a2, i64 4
291  ret ptr %a3
292}
293
294define ptr @geps_combinable_scalable(ptr %a, i64 %idx) {
295; CHECK-LABEL: @geps_combinable_scalable(
296; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
297; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 3
298; CHECK-NEXT:    [[A2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[TMP2]]
299; CHECK-NEXT:    [[A3:%.*]] = getelementptr inbounds nuw i8, ptr [[A2]], i64 4
300; CHECK-NEXT:    ret ptr [[A3]]
301;
302  %a2 = getelementptr inbounds <vscale x 2 x i32>, ptr %a, i64 1
303  %a3 = getelementptr inbounds i8, ptr %a2, i32 4
304  ret ptr %a3
305}
306
307define ptr @geps_combinable_scalable_vector_array(ptr %a, i64 %idx) {
308; CHECK-LABEL: @geps_combinable_scalable_vector_array(
309; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
310; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 5
311; CHECK-NEXT:    [[A2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[TMP2]]
312; CHECK-NEXT:    [[A3:%.*]] = getelementptr inbounds nuw i8, ptr [[A2]], i64 4
313; CHECK-NEXT:    ret ptr [[A3]]
314;
315  %a2 = getelementptr inbounds [4 x <vscale x 2 x i32>], ptr %a, i64 1
316  %a3 = getelementptr inbounds i8, ptr %a2, i32 4
317  ret ptr %a3
318}
319
320define i1 @compare_geps_same_indices(ptr %a, ptr %b, i64 %idx) {
321; CHECK-LABEL: @compare_geps_same_indices(
322; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[A:%.*]], [[B:%.*]]
323; CHECK-NEXT:    ret i1 [[C]]
324;
325  %a2 = getelementptr i32, ptr %a, i64 %idx
326  %b2 = getelementptr i32, ptr %b, i64 %idx
327  %c = icmp eq ptr %a2, %b2
328  ret i1 %c
329}
330
331define i1 @compare_geps_same_indices_different_types(ptr %a, ptr %b, i64 %idx) {
332; CHECK-LABEL: @compare_geps_same_indices_different_types(
333; CHECK-NEXT:    [[A2:%.*]] = getelementptr i32, ptr [[A:%.*]], i64 [[IDX:%.*]]
334; CHECK-NEXT:    [[B2:%.*]] = getelementptr i64, ptr [[B:%.*]], i64 [[IDX]]
335; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[A2]], [[B2]]
336; CHECK-NEXT:    ret i1 [[C]]
337;
338  %a2 = getelementptr i32, ptr %a, i64 %idx
339  %b2 = getelementptr i64, ptr %b, i64 %idx
340  %c = icmp eq ptr %a2, %b2
341  ret i1 %c
342}
343
344define i1 @compare_gep_with_base(ptr %p, i64 %idx) {
345; CHECK-LABEL: @compare_gep_with_base(
346; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[IDX:%.*]], 0
347; CHECK-NEXT:    ret i1 [[C]]
348;
349  %gep = getelementptr inbounds i32, ptr %p, i64 %idx
350  %c = icmp eq ptr %gep, %p
351  ret i1 %c
352}
353
354define <2 x i1> @compare_gep_with_base_vector1(<2 x ptr> %p, i64 %idx) {
355; CHECK-LABEL: @compare_gep_with_base_vector1(
356; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[IDX:%.*]], i64 0
357; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0>
358; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], zeroinitializer
359; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer
360; CHECK-NEXT:    ret <2 x i1> [[C]]
361;
362  %gep = getelementptr inbounds i32, <2 x ptr> %p, i64 %idx
363  %c = icmp eq <2 x ptr> %gep, %p
364  ret <2 x i1> %c
365}
366
367define <2 x i1> @compare_gep_with_base_vector2(<2 x ptr> %p, <2 x i64> %idx) {
368; CHECK-LABEL: @compare_gep_with_base_vector2(
369; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[IDX:%.*]], zeroinitializer
370; CHECK-NEXT:    ret <2 x i1> [[C]]
371;
372  %gep = getelementptr inbounds i32, <2 x ptr> %p, <2 x i64> %idx
373  %c = icmp eq <2 x ptr> %gep, %p
374  ret <2 x i1> %c
375}
376
377define <4 x i1> @compare_geps_same_indices_scalar_vector_base_mismatch(ptr %ptr, <4 x ptr> %ptrs) {
378; CHECK-LABEL: @compare_geps_same_indices_scalar_vector_base_mismatch(
379; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i16, <4 x ptr> [[PTRS:%.*]], <4 x i64> <i64 1, i64 2, i64 3, i64 4>
380; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i16, ptr [[PTR:%.*]], <4 x i64> <i64 1, i64 2, i64 3, i64 4>
381; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <4 x ptr> [[GEP1]], [[GEP2]]
382; CHECK-NEXT:    ret <4 x i1> [[CMP]]
383;
384  %gep1 = getelementptr i16, <4 x ptr> %ptrs, <4 x i64> <i64 1, i64 2, i64 3, i64 4>
385  %gep2 = getelementptr i16, ptr %ptr, <4 x i64> <i64 1, i64 2, i64 3, i64 4>
386  %cmp = icmp eq <4 x ptr> %gep1, %gep2
387  ret <4 x i1> %cmp
388}
389
390define ptr @indexed_compare(ptr %A, i64 %offset) {
391; CHECK-LABEL: @indexed_compare(
392; CHECK-NEXT:  entry:
393; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 2
394; CHECK-NEXT:    br label [[BB:%.*]]
395; CHECK:       bb:
396; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i64 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
397; CHECK-NEXT:    [[RHS_ADD]] = add nsw i64 [[RHS_IDX]], 4
398; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i64 [[RHS_IDX]], 400
399; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
400; CHECK:       bb2:
401; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[RHS_IDX]]
402; CHECK-NEXT:    ret ptr [[RHS_PTR]]
403;
404entry:
405  %tmp = getelementptr inbounds i32, ptr %A, i64 %offset
406  br label %bb
407
408bb:
409  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
410  %LHS = getelementptr inbounds i32, ptr %A, i32 100
411  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
412  %cond = icmp ult ptr %LHS, %RHS
413  br i1 %cond, label %bb2, label %bb
414
415bb2:
416  ret ptr %RHS
417}
418
419define ptr @indexed_compare_different_types(ptr %A, i64 %offset) {
420; CHECK-LABEL: @indexed_compare_different_types(
421; CHECK-NEXT:  entry:
422; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 2
423; CHECK-NEXT:    br label [[BB:%.*]]
424; CHECK:       bb:
425; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i64 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
426; CHECK-NEXT:    [[RHS_ADD]] = add nsw i64 [[RHS_IDX]], 4
427; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i64 [[RHS_IDX]], 800
428; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
429; CHECK:       bb2:
430; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[RHS_IDX]]
431; CHECK-NEXT:    ret ptr [[RHS_PTR]]
432;
433entry:
434  %tmp = getelementptr inbounds i32, ptr %A, i64 %offset
435  br label %bb
436
437bb:
438  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
439  %LHS = getelementptr inbounds i64, ptr %A, i32 100
440  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
441  %cond = icmp ult ptr %LHS, %RHS
442  br i1 %cond, label %bb2, label %bb
443
444bb2:
445  ret ptr %RHS
446}
447
448define ptr addrspace(1) @gep_of_addrspace_cast(ptr %ptr) {
449; CHECK-LABEL: @gep_of_addrspace_cast(
450; CHECK-NEXT:    [[CAST1:%.*]] = addrspacecast ptr [[PTR:%.*]] to ptr addrspace(1)
451; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[CAST1]], i64 4
452; CHECK-NEXT:    ret ptr addrspace(1) [[GEP]]
453;
454  %cast1 = addrspacecast ptr %ptr to ptr addrspace(1)
455  %gep = getelementptr inbounds i32, ptr addrspace(1) %cast1, i64 1
456  ret ptr addrspace(1) %gep
457}
458
459define i1 @cmp_gep_same_base_same_type(ptr %ptr, i64 %idx1, i64 %idx2) {
460; CHECK-LABEL: @cmp_gep_same_base_same_type(
461; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IDX1:%.*]], [[IDX2:%.*]]
462; CHECK-NEXT:    ret i1 [[CMP]]
463;
464  %gep1 = getelementptr inbounds i32, ptr %ptr, i64 %idx1
465  %gep2 = getelementptr inbounds i32, ptr %ptr, i64 %idx2
466  %cmp = icmp ult ptr %gep1, %gep2
467  ret i1 %cmp
468}
469
470define i1 @cmp_gep_same_base_different_type(ptr %ptr, i64 %idx1, i64 %idx2) {
471; CHECK-LABEL: @cmp_gep_same_base_different_type(
472; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[IDX1:%.*]], 2
473; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nsw i64 [[IDX2:%.*]], 3
474; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]
475; CHECK-NEXT:    ret i1 [[CMP]]
476;
477  %gep1 = getelementptr inbounds i32, ptr %ptr, i64 %idx1
478  %gep2 = getelementptr inbounds i64, ptr %ptr, i64 %idx2
479  %cmp = icmp ult ptr %gep1, %gep2
480  ret i1 %cmp
481}
482
483@ary = constant [4 x i8] [i8 1, i8 2, i8 3, i8 4]
484
485define i1 @cmp_load_gep_global(i64 %idx) {
486; CHECK-LABEL: @cmp_load_gep_global(
487; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IDX:%.*]], 2
488; CHECK-NEXT:    ret i1 [[CMP]]
489;
490  %gep = getelementptr [4 x i8], ptr @ary, i64 0, i64 %idx
491  %load = load i8, ptr %gep
492  %cmp = icmp eq i8 %load, 3
493  ret i1 %cmp
494}
495
496define i1 @cmp_load_gep_global_different_load_type(i64 %idx) {
497; CHECK-LABEL: @cmp_load_gep_global_different_load_type(
498; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [4 x i8], ptr @ary, i64 0, i64 [[IDX:%.*]]
499; CHECK-NEXT:    [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
500; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[LOAD]], 3
501; CHECK-NEXT:    ret i1 [[CMP]]
502;
503  %gep = getelementptr [4 x i8], ptr @ary, i64 0, i64 %idx
504  %load = load i16, ptr %gep
505  %cmp = icmp eq i16 %load, 3
506  ret i1 %cmp
507}
508
509define i1 @cmp_load_gep_global_different_gep_type(i64 %idx) {
510; CHECK-LABEL: @cmp_load_gep_global_different_gep_type(
511; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [4 x i16], ptr @ary, i64 0, i64 [[IDX:%.*]]
512; CHECK-NEXT:    [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
513; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[LOAD]], 3
514; CHECK-NEXT:    ret i1 [[CMP]]
515;
516  %gep = getelementptr [4 x i16], ptr @ary, i64 0, i64 %idx
517  %load = load i16, ptr %gep
518  %cmp = icmp eq i16 %load, 3
519  ret i1 %cmp
520}
521
522define ptr @phi_of_gep(i1 %c, ptr %p) {
523; CHECK-LABEL: @phi_of_gep(
524; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
525; CHECK:       if:
526; CHECK-NEXT:    br label [[JOIN:%.*]]
527; CHECK:       else:
528; CHECK-NEXT:    br label [[JOIN]]
529; CHECK:       join:
530; CHECK-NEXT:    [[PHI:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
531; CHECK-NEXT:    ret ptr [[PHI]]
532;
533  br i1 %c, label %if, label %else
534
535if:
536  %gep1 = getelementptr i32, ptr %p, i64 1
537  br label %join
538
539else:
540  %gep2 = getelementptr i32, ptr %p, i64 1
541  br label %join
542
543join:
544  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
545  ret ptr %phi
546}
547
548define ptr @phi_of_gep_flags_1(i1 %c, ptr %p) {
549; CHECK-LABEL: @phi_of_gep_flags_1(
550; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
551; CHECK:       if:
552; CHECK-NEXT:    br label [[JOIN:%.*]]
553; CHECK:       else:
554; CHECK-NEXT:    br label [[JOIN]]
555; CHECK:       join:
556; CHECK-NEXT:    [[PHI:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 4
557; CHECK-NEXT:    ret ptr [[PHI]]
558;
559  br i1 %c, label %if, label %else
560
561if:
562  %gep1 = getelementptr inbounds i32, ptr %p, i64 1
563  br label %join
564
565else:
566  %gep2 = getelementptr nusw nuw i32, ptr %p, i64 1
567  br label %join
568
569join:
570  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
571  ret ptr %phi
572}
573
574define ptr @phi_of_gep_flags_2(i1 %c, ptr %p) {
575; CHECK-LABEL: @phi_of_gep_flags_2(
576; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
577; CHECK:       if:
578; CHECK-NEXT:    br label [[JOIN:%.*]]
579; CHECK:       else:
580; CHECK-NEXT:    br label [[JOIN]]
581; CHECK:       join:
582; CHECK-NEXT:    [[PHI:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 4
583; CHECK-NEXT:    ret ptr [[PHI]]
584;
585  br i1 %c, label %if, label %else
586
587if:
588  %gep1 = getelementptr nusw nuw i32, ptr %p, i64 1
589  br label %join
590
591else:
592  %gep2 = getelementptr nuw i32, ptr %p, i64 1
593  br label %join
594
595join:
596  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
597  ret ptr %phi
598}
599
600define ptr @phi_of_gep_different_type(i1 %c, ptr %p) {
601; CHECK-LABEL: @phi_of_gep_different_type(
602; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
603; CHECK:       if:
604; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
605; CHECK-NEXT:    br label [[JOIN:%.*]]
606; CHECK:       else:
607; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[P]], i64 8
608; CHECK-NEXT:    br label [[JOIN]]
609; CHECK:       join:
610; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[GEP1]], [[IF]] ], [ [[GEP2]], [[ELSE]] ]
611; CHECK-NEXT:    ret ptr [[PHI]]
612;
613  br i1 %c, label %if, label %else
614
615if:
616  %gep1 = getelementptr i32, ptr %p, i64 1
617  br label %join
618
619else:
620  %gep2 = getelementptr i64, ptr %p, i64 1
621  br label %join
622
623join:
624  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
625  ret ptr %phi
626}
627
628define ptr @gep_of_phi_of_gep(i1 %c, ptr %p) {
629; CHECK-LABEL: @gep_of_phi_of_gep(
630; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
631; CHECK:       if:
632; CHECK-NEXT:    br label [[JOIN:%.*]]
633; CHECK:       else:
634; CHECK-NEXT:    br label [[JOIN]]
635; CHECK:       join:
636; CHECK-NEXT:    [[TMP1:%.*]] = phi i64 [ 4, [[IF]] ], [ 8, [[ELSE]] ]
637; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP1]]
638; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 4
639; CHECK-NEXT:    ret ptr [[GEP]]
640;
641  br i1 %c, label %if, label %else
642
643if:
644  %gep1 = getelementptr i32, ptr %p, i64 1
645  br label %join
646
647else:
648  %gep2 = getelementptr i32, ptr %p, i64 2
649  br label %join
650
651join:
652  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
653  %gep = getelementptr i32, ptr %phi, i64 1
654  ret ptr %gep
655}
656
657define ptr @gep_of_phi_of_gep_flags1(i1 %c, ptr %p) {
658; CHECK-LABEL: @gep_of_phi_of_gep_flags1(
659; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
660; CHECK:       if:
661; CHECK-NEXT:    br label [[JOIN:%.*]]
662; CHECK:       else:
663; CHECK-NEXT:    br label [[JOIN]]
664; CHECK:       join:
665; CHECK-NEXT:    [[TMP1:%.*]] = phi i64 [ 4, [[IF]] ], [ 8, [[ELSE]] ]
666; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP1]]
667; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 4
668; CHECK-NEXT:    ret ptr [[GEP]]
669;
670  br i1 %c, label %if, label %else
671
672if:
673  %gep1 = getelementptr inbounds i32, ptr %p, i64 1
674  br label %join
675
676else:
677  %gep2 = getelementptr i32, ptr %p, i64 2
678  br label %join
679
680join:
681  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
682  %gep = getelementptr i32, ptr %phi, i64 1
683  ret ptr %gep
684}
685
686define ptr @gep_of_phi_of_gep_flags2(i1 %c, ptr %p) {
687; CHECK-LABEL: @gep_of_phi_of_gep_flags2(
688; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
689; CHECK:       if:
690; CHECK-NEXT:    br label [[JOIN:%.*]]
691; CHECK:       else:
692; CHECK-NEXT:    br label [[JOIN]]
693; CHECK:       join:
694; CHECK-NEXT:    [[TMP1:%.*]] = phi i64 [ 4, [[IF]] ], [ 8, [[ELSE]] ]
695; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[TMP1]]
696; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 4
697; CHECK-NEXT:    ret ptr [[GEP]]
698;
699  br i1 %c, label %if, label %else
700
701if:
702  %gep1 = getelementptr nuw i32, ptr %p, i64 1
703  br label %join
704
705else:
706  %gep2 = getelementptr nuw i32, ptr %p, i64 2
707  br label %join
708
709join:
710  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
711  %gep = getelementptr i32, ptr %phi, i64 1
712  ret ptr %gep
713}
714
715define ptr @gep_of_phi_of_gep_different_type(i1 %c, ptr %p) {
716; CHECK-LABEL: @gep_of_phi_of_gep_different_type(
717; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
718; CHECK:       if:
719; CHECK-NEXT:    br label [[JOIN:%.*]]
720; CHECK:       else:
721; CHECK-NEXT:    br label [[JOIN]]
722; CHECK:       join:
723; CHECK-NEXT:    [[TMP1:%.*]] = phi i64 [ 4, [[IF]] ], [ 16, [[ELSE]] ]
724; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP1]]
725; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 4
726; CHECK-NEXT:    ret ptr [[GEP]]
727;
728  br i1 %c, label %if, label %else
729
730if:
731  %gep1 = getelementptr i32, ptr %p, i64 1
732  br label %join
733
734else:
735  %gep2 = getelementptr i64, ptr %p, i64 2
736  br label %join
737
738join:
739  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
740  %gep = getelementptr i32, ptr %phi, i64 1
741  ret ptr %gep
742}
743
744define ptr @select_of_gep(i1 %c, ptr %p) {
745; CHECK-LABEL: @select_of_gep(
746; CHECK-NEXT:    [[S_V:%.*]] = select i1 [[C:%.*]], i64 4, i64 8
747; CHECK-NEXT:    [[S:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[S_V]]
748; CHECK-NEXT:    ret ptr [[S]]
749;
750  %gep1 = getelementptr i32, ptr %p, i64 1
751  %gep2 = getelementptr i32, ptr %p, i64 2
752  %s = select i1 %c, ptr %gep1, ptr %gep2
753  ret ptr %s
754}
755
756define ptr @select_of_gep_flags_1(i1 %c, ptr %p) {
757; CHECK-LABEL: @select_of_gep_flags_1(
758; CHECK-NEXT:    [[S_V:%.*]] = select i1 [[C:%.*]], i64 4, i64 8
759; CHECK-NEXT:    [[S:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 [[S_V]]
760; CHECK-NEXT:    ret ptr [[S]]
761;
762  %gep1 = getelementptr inbounds i32, ptr %p, i64 1
763  %gep2 = getelementptr nusw nuw i32, ptr %p, i64 2
764  %s = select i1 %c, ptr %gep1, ptr %gep2
765  ret ptr %s
766}
767
768define ptr @select_of_gep_flags_2(i1 %c, ptr %p) {
769; CHECK-LABEL: @select_of_gep_flags_2(
770; CHECK-NEXT:    [[S_V:%.*]] = select i1 [[C:%.*]], i64 4, i64 8
771; CHECK-NEXT:    [[S:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[S_V]]
772; CHECK-NEXT:    ret ptr [[S]]
773;
774  %gep1 = getelementptr nuw i32, ptr %p, i64 1
775  %gep2 = getelementptr nusw nuw i32, ptr %p, i64 2
776  %s = select i1 %c, ptr %gep1, ptr %gep2
777  ret ptr %s
778}
779
780define ptr @select_of_gep_different_type(i1 %c, ptr %p) {
781; CHECK-LABEL: @select_of_gep_different_type(
782; CHECK-NEXT:    [[S_V:%.*]] = select i1 [[C:%.*]], i64 4, i64 16
783; CHECK-NEXT:    [[S:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[S_V]]
784; CHECK-NEXT:    ret ptr [[S]]
785;
786  %gep1 = getelementptr i32, ptr %p, i64 1
787  %gep2 = getelementptr i64, ptr %p, i64 2
788  %s = select i1 %c, ptr %gep1, ptr %gep2
789  ret ptr %s
790}
791
792define void @dse(ptr %p) {
793; CHECK-LABEL: @dse(
794; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
795; CHECK-NEXT:    store i8 1, ptr [[P]], align 1
796; CHECK-NEXT:    ret void
797;
798  store i32 0, ptr %p
799  store i8 1, ptr %p
800  ret void
801}
802
803declare void @call_i64(i64)
804declare void @call_byval(i64, ptr byval(i64))
805
806define void @call_cast_ptr_to_int(ptr %p) {
807; CHECK-LABEL: @call_cast_ptr_to_int(
808; CHECK-NEXT:    call void @call_i64(ptr [[P:%.*]])
809; CHECK-NEXT:    ret void
810;
811  call void @call_i64(ptr %p)
812  ret void
813}
814
815define void @call_cast_byval(ptr %p, ptr %p2) {
816; CHECK-LABEL: @call_cast_byval(
817; CHECK-NEXT:    call void @call_byval(ptr [[P:%.*]], ptr byval(double) [[P2:%.*]])
818; CHECK-NEXT:    ret void
819;
820  call void @call_byval(ptr %p, ptr byval(double) %p2)
821  ret void
822}
823
824declare float @fmodf(float, float)
825
826define i32 @const_fold_call_with_func_type_mismatch() {
827; CHECK-LABEL: @const_fold_call_with_func_type_mismatch(
828; CHECK-NEXT:    [[V:%.*]] = call i32 @fmodf(float 0x40091EB860000000, float 2.000000e+00)
829; CHECK-NEXT:    ret i32 [[V]]
830;
831  %v = call i32 @fmodf(float 0x40091EB860000000, float 2.000000e+00)
832  ret i32 %v
833}
834