1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -instcombine < %s | FileCheck %s
3
4target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
5
6define i64 @test_inbounds([0 x i32]* %base, i64 %idx) {
7; CHECK-LABEL: @test_inbounds(
8; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
9; CHECK-NEXT:    ret i64 [[P2_IDX]]
10;
11  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
12  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
13  %i1 = ptrtoint i32* %p1 to i64
14  %i2 = ptrtoint i32* %p2 to i64
15  %d = sub i64 %i2, %i1
16  ret i64 %d
17}
18
19define i64 @test_partial_inbounds1([0 x i32]* %base, i64 %idx) {
20; CHECK-LABEL: @test_partial_inbounds1(
21; CHECK-NEXT:    [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2
22; CHECK-NEXT:    ret i64 [[P2_IDX]]
23;
24  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
25  %p2 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
26  %i1 = ptrtoint i32* %p1 to i64
27  %i2 = ptrtoint i32* %p2 to i64
28  %d = sub i64 %i2, %i1
29  ret i64 %d
30}
31
32define i64 @test_partial_inbounds2([0 x i32]* %base, i64 %idx) {
33; CHECK-LABEL: @test_partial_inbounds2(
34; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
35; CHECK-NEXT:    ret i64 [[P2_IDX]]
36;
37  %p1 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 0
38  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
39  %i1 = ptrtoint i32* %p1 to i64
40  %i2 = ptrtoint i32* %p2 to i64
41  %d = sub i64 %i2, %i1
42  ret i64 %d
43}
44
45define i64 @test_inbounds_nuw([0 x i32]* %base, i64 %idx) {
46; CHECK-LABEL: @test_inbounds_nuw(
47; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nuw nsw i64 [[IDX:%.*]], 2
48; CHECK-NEXT:    ret i64 [[P2_IDX]]
49;
50  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
51  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
52  %i1 = ptrtoint i32* %p1 to i64
53  %i2 = ptrtoint i32* %p2 to i64
54  %d = sub nuw i64 %i2, %i1
55  ret i64 %d
56}
57
58define i64 @test_nuw([0 x i32]* %base, i64 %idx) {
59; CHECK-LABEL: @test_nuw(
60; CHECK-NEXT:    [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2
61; CHECK-NEXT:    ret i64 [[P2_IDX]]
62;
63  %p1 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 0
64  %p2 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
65  %i1 = ptrtoint i32* %p1 to i64
66  %i2 = ptrtoint i32* %p2 to i64
67  %d = sub nuw i64 %i2, %i1
68  ret i64 %d
69}
70
71define i32 @test_inbounds_nuw_trunc([0 x i32]* %base, i64 %idx) {
72; CHECK-LABEL: @test_inbounds_nuw_trunc(
73; CHECK-NEXT:    [[IDX_TR:%.*]] = trunc i64 [[IDX:%.*]] to i32
74; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[IDX_TR]], 2
75; CHECK-NEXT:    ret i32 [[TMP1]]
76;
77  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
78  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
79  %i1 = ptrtoint i32* %p1 to i64
80  %i2 = ptrtoint i32* %p2 to i64
81  %t1 = trunc i64 %i1 to i32
82  %t2 = trunc i64 %i2 to i32
83  %d = sub nuw i32 %t2, %t1
84  ret i32 %d
85}
86
87define i64 @test_inbounds_nuw_swapped([0 x i32]* %base, i64 %idx) {
88; CHECK-LABEL: @test_inbounds_nuw_swapped(
89; CHECK-NEXT:    [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
90; CHECK-NEXT:    ret i64 [[P2_IDX_NEG]]
91;
92  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
93  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
94  %i1 = ptrtoint i32* %p2 to i64
95  %i2 = ptrtoint i32* %p1 to i64
96  %d = sub nuw i64 %i2, %i1
97  ret i64 %d
98}
99
100define i64 @test_inbounds1_nuw_swapped([0 x i32]* %base, i64 %idx) {
101; CHECK-LABEL: @test_inbounds1_nuw_swapped(
102; CHECK-NEXT:    [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
103; CHECK-NEXT:    ret i64 [[P2_IDX_NEG]]
104;
105  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
106  %p2 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
107  %i1 = ptrtoint i32* %p2 to i64
108  %i2 = ptrtoint i32* %p1 to i64
109  %d = sub nuw i64 %i2, %i1
110  ret i64 %d
111}
112
113define i64 @test_inbounds2_nuw_swapped([0 x i32]* %base, i64 %idx) {
114; CHECK-LABEL: @test_inbounds2_nuw_swapped(
115; CHECK-NEXT:    [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
116; CHECK-NEXT:    ret i64 [[P2_IDX_NEG]]
117;
118  %p1 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 0
119  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
120  %i1 = ptrtoint i32* %p2 to i64
121  %i2 = ptrtoint i32* %p1 to i64
122  %d = sub nuw i64 %i2, %i1
123  ret i64 %d
124}
125
126define i64 @test_inbounds_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) {
127; CHECK-LABEL: @test_inbounds_two_gep(
128; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
129; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
130; CHECK-NEXT:    ret i64 [[GEPDIFF]]
131;
132  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
133  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx2
134  %i1 = ptrtoint i32* %p1 to i64
135  %i2 = ptrtoint i32* %p2 to i64
136  %d = sub i64 %i2, %i1
137  ret i64 %d
138}
139
140define i64 @test_inbounds_nsw_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) {
141; CHECK-LABEL: @test_inbounds_nsw_two_gep(
142; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
143; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
144; CHECK-NEXT:    ret i64 [[GEPDIFF]]
145;
146  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
147  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx2
148  %i1 = ptrtoint i32* %p1 to i64
149  %i2 = ptrtoint i32* %p2 to i64
150  %d = sub nsw i64 %i2, %i1
151  ret i64 %d
152}
153
154define i64 @test_inbounds_nuw_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) {
155; CHECK-LABEL: @test_inbounds_nuw_two_gep(
156; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
157; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
158; CHECK-NEXT:    ret i64 [[GEPDIFF]]
159;
160  %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
161  %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx2
162  %i1 = ptrtoint i32* %p1 to i64
163  %i2 = ptrtoint i32* %p2 to i64
164  %d = sub nuw i64 %i2, %i1
165  ret i64 %d
166}
167
168define i64 @test_inbounds_nuw_multi_index([0 x [2 x i32]]* %base, i64 %idx, i64 %idx2) {
169; CHECK-LABEL: @test_inbounds_nuw_multi_index(
170; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 3
171; CHECK-NEXT:    [[P2_IDX1:%.*]] = shl nsw i64 [[IDX2:%.*]], 2
172; CHECK-NEXT:    [[P2_OFFS:%.*]] = add nsw i64 [[P2_IDX]], [[P2_IDX1]]
173; CHECK-NEXT:    ret i64 [[P2_OFFS]]
174;
175  %p1 = getelementptr inbounds [0 x [2 x i32]], [0 x [2 x i32]]* %base, i64 0, i64 0, i64 0
176  %p2 = getelementptr inbounds [0 x [2 x i32]], [0 x [2 x i32]]* %base, i64 0, i64 %idx, i64 %idx2
177  %i1 = ptrtoint i32* %p1 to i64
178  %i2 = ptrtoint i32* %p2 to i64
179  %d = sub nuw i64 %i2, %i1
180  ret i64 %d
181}
182
183; rdar://7362831
184define i32 @test23(i8* %P, i64 %A){
185; CHECK-LABEL: @test23(
186; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i32
187; CHECK-NEXT:    ret i32 [[TMP1]]
188;
189  %B = getelementptr inbounds i8, i8* %P, i64 %A
190  %C = ptrtoint i8* %B to i64
191  %D = trunc i64 %C to i32
192  %E = ptrtoint i8* %P to i64
193  %F = trunc i64 %E to i32
194  %G = sub i32 %D, %F
195  ret i32 %G
196}
197
198define i8 @test23_as1(i8 addrspace(1)* %P, i16 %A) {
199; CHECK-LABEL: @test23_as1(
200; CHECK-NEXT:    [[TMP1:%.*]] = trunc i16 [[A:%.*]] to i8
201; CHECK-NEXT:    ret i8 [[TMP1]]
202;
203  %B = getelementptr inbounds i8, i8 addrspace(1)* %P, i16 %A
204  %C = ptrtoint i8 addrspace(1)* %B to i16
205  %D = trunc i16 %C to i8
206  %E = ptrtoint i8 addrspace(1)* %P to i16
207  %F = trunc i16 %E to i8
208  %G = sub i8 %D, %F
209  ret i8 %G
210}
211
212define i64 @test24(i8* %P, i64 %A){
213; CHECK-LABEL: @test24(
214; CHECK-NEXT:    ret i64 [[A:%.*]]
215;
216  %B = getelementptr inbounds i8, i8* %P, i64 %A
217  %C = ptrtoint i8* %B to i64
218  %E = ptrtoint i8* %P to i64
219  %G = sub i64 %C, %E
220  ret i64 %G
221}
222
223define i16 @test24_as1(i8 addrspace(1)* %P, i16 %A) {
224; CHECK-LABEL: @test24_as1(
225; CHECK-NEXT:    ret i16 [[A:%.*]]
226;
227  %B = getelementptr inbounds i8, i8 addrspace(1)* %P, i16 %A
228  %C = ptrtoint i8 addrspace(1)* %B to i16
229  %E = ptrtoint i8 addrspace(1)* %P to i16
230  %G = sub i16 %C, %E
231  ret i16 %G
232}
233
234define i64 @test24a(i8* %P, i64 %A){
235; CHECK-LABEL: @test24a(
236; CHECK-NEXT:    [[DIFF_NEG:%.*]] = sub i64 0, [[A:%.*]]
237; CHECK-NEXT:    ret i64 [[DIFF_NEG]]
238;
239  %B = getelementptr inbounds i8, i8* %P, i64 %A
240  %C = ptrtoint i8* %B to i64
241  %E = ptrtoint i8* %P to i64
242  %G = sub i64 %E, %C
243  ret i64 %G
244}
245
246define i16 @test24a_as1(i8 addrspace(1)* %P, i16 %A) {
247; CHECK-LABEL: @test24a_as1(
248; CHECK-NEXT:    [[DIFF_NEG:%.*]] = sub i16 0, [[A:%.*]]
249; CHECK-NEXT:    ret i16 [[DIFF_NEG]]
250;
251  %B = getelementptr inbounds i8, i8 addrspace(1)* %P, i16 %A
252  %C = ptrtoint i8 addrspace(1)* %B to i16
253  %E = ptrtoint i8 addrspace(1)* %P to i16
254  %G = sub i16 %E, %C
255  ret i16 %G
256}
257
258@Arr = external global [42 x i16]
259
260define i64 @test24b(i8* %P, i64 %A){
261; CHECK-LABEL: @test24b(
262; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
263; CHECK-NEXT:    ret i64 [[B_IDX]]
264;
265  %B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A
266  %C = ptrtoint i16* %B to i64
267  %G = sub i64 %C, ptrtoint ([42 x i16]* @Arr to i64)
268  ret i64 %G
269}
270
271define i64 @test25(i8* %P, i64 %A){
272; CHECK-LABEL: @test25(
273; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
274; CHECK-NEXT:    [[GEPDIFF:%.*]] = add nsw i64 [[B_IDX]], -84
275; CHECK-NEXT:    ret i64 [[GEPDIFF]]
276;
277  %B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A
278  %C = ptrtoint i16* %B to i64
279  %G = sub i64 %C, ptrtoint (i16* getelementptr ([42 x i16], [42 x i16]* @Arr, i64 1, i64 0) to i64)
280  ret i64 %G
281}
282
283@Arr_as1 = external addrspace(1) global [42 x i16]
284
285define i16 @test25_as1(i8 addrspace(1)* %P, i64 %A) {
286; CHECK-LABEL: @test25_as1(
287; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16
288; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw i16 [[TMP1]], 1
289; CHECK-NEXT:    [[GEPDIFF:%.*]] = add nsw i16 [[B_IDX]], -84
290; CHECK-NEXT:    ret i16 [[GEPDIFF]]
291;
292  %B = getelementptr inbounds [42 x i16], [42 x i16] addrspace(1)* @Arr_as1, i64 0, i64 %A
293  %C = ptrtoint i16 addrspace(1)* %B to i16
294  %G = sub i16 %C, ptrtoint (i16 addrspace(1)* getelementptr ([42 x i16], [42 x i16] addrspace(1)* @Arr_as1, i64 1, i64 0) to i16)
295  ret i16 %G
296}
297
298define i64 @test30(i8* %foo, i64 %i, i64 %j) {
299; CHECK-LABEL: @test30(
300; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
301; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub nsw i64 [[GEP1_IDX]], [[J:%.*]]
302; CHECK-NEXT:    ret i64 [[GEPDIFF]]
303;
304  %bit = bitcast i8* %foo to i32*
305  %gep1 = getelementptr inbounds i32, i32* %bit, i64 %i
306  %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
307  %cast1 = ptrtoint i32* %gep1 to i64
308  %cast2 = ptrtoint i8* %gep2 to i64
309  %sub = sub i64 %cast1, %cast2
310  ret i64 %sub
311}
312
313define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
314; CHECK-LABEL: @test30_as1(
315; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
316; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub nsw i16 [[GEP1_IDX]], [[J:%.*]]
317; CHECK-NEXT:    ret i16 [[GEPDIFF]]
318;
319  %bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
320  %gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i16 %i
321  %gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i16 %j
322  %cast1 = ptrtoint i32 addrspace(1)* %gep1 to i16
323  %cast2 = ptrtoint i8 addrspace(1)* %gep2 to i16
324  %sub = sub i16 %cast1, %cast2
325  ret i16 %sub
326}
327
328; Inbounds translates to 'nsw' on sub
329
330define i64 @gep_diff_both_inbounds(i8* %foo, i64 %i, i64 %j) {
331; CHECK-LABEL: @gep_diff_both_inbounds(
332; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub nsw i64 [[I:%.*]], [[J:%.*]]
333; CHECK-NEXT:    ret i64 [[GEPDIFF]]
334;
335  %gep1 = getelementptr inbounds i8, i8* %foo, i64 %i
336  %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
337  %cast1 = ptrtoint i8* %gep1 to i64
338  %cast2 = ptrtoint i8* %gep2 to i64
339  %sub = sub i64 %cast1, %cast2
340  ret i64 %sub
341}
342
343; Negative test for 'nsw' - both geps must be inbounds
344
345define i64 @gep_diff_first_inbounds(i8* %foo, i64 %i, i64 %j) {
346; CHECK-LABEL: @gep_diff_first_inbounds(
347; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
348; CHECK-NEXT:    ret i64 [[GEPDIFF]]
349;
350  %gep1 = getelementptr inbounds i8, i8* %foo, i64 %i
351  %gep2 = getelementptr i8, i8* %foo, i64 %j
352  %cast1 = ptrtoint i8* %gep1 to i64
353  %cast2 = ptrtoint i8* %gep2 to i64
354  %sub = sub i64 %cast1, %cast2
355  ret i64 %sub
356}
357
358; Negative test for 'nsw' - both geps must be inbounds
359
360define i64 @gep_diff_second_inbounds(i8* %foo, i64 %i, i64 %j) {
361; CHECK-LABEL: @gep_diff_second_inbounds(
362; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
363; CHECK-NEXT:    ret i64 [[GEPDIFF]]
364;
365  %gep1 = getelementptr i8, i8* %foo, i64 %i
366  %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
367  %cast1 = ptrtoint i8* %gep1 to i64
368  %cast2 = ptrtoint i8* %gep2 to i64
369  %sub = sub i64 %cast1, %cast2
370  ret i64 %sub
371}
372