[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / InstCombine / icmp-gep.ll
blob4b5116c36f6fbf73520b62f3376219d4d9d149e2
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S  < %s | FileCheck %s
4 target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-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-n8:16:32:64"
6 declare i8* @getptr()
7 declare void @use(i8*)
9 define i1 @eq_base(i8* %x, i64 %y) {
10 ; CHECK-LABEL: @eq_base(
11 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, i8* [[X:%.*]], i64 [[Y:%.*]]
12 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i8* [[G]], [[X]]
13 ; CHECK-NEXT:    ret i1 [[R]]
15   %g = getelementptr i8, i8* %x, i64 %y
16   %r = icmp eq i8* %g, %x
17   ret i1 %r
20 define i1 @ne_base_commute(i64 %y) {
21 ; CHECK-LABEL: @ne_base_commute(
22 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
23 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, i8* [[X]], i64 [[Y:%.*]]
24 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8* [[X]], [[G]]
25 ; CHECK-NEXT:    ret i1 [[R]]
27   %x = call i8* @getptr() ; thwart complexity-based canonicalization
28   %g = getelementptr i8, i8* %x, i64 %y
29   %r = icmp ne i8* %x, %g
30   ret i1 %r
33 define i1 @ne_base_inbounds(i8* %x, i64 %y) {
34 ; CHECK-LABEL: @ne_base_inbounds(
35 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
36 ; CHECK-NEXT:    ret i1 [[R]]
38   %g = getelementptr inbounds i8, i8* %x, i64 %y
39   %r = icmp ne i8* %g, %x
40   ret i1 %r
43 define i1 @eq_base_inbounds_commute(i64 %y) {
44 ; CHECK-LABEL: @eq_base_inbounds_commute(
45 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
46 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y:%.*]], 0
47 ; CHECK-NEXT:    ret i1 [[R]]
49   %x = call i8* @getptr() ; thwart complexity-based canonicalization
50   %g = getelementptr inbounds i8, i8* %x, i64 %y
51   %r = icmp eq i8* %x, %g
52   ret i1 %r
55 define i1 @slt_base(i8* %x, i64 %y) {
56 ; CHECK-LABEL: @slt_base(
57 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, i8* [[X:%.*]], i64 [[Y:%.*]]
58 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i8* [[G]], [[X]]
59 ; CHECK-NEXT:    ret i1 [[R]]
61   %g = getelementptr i8, i8* %x, i64 %y
62   %r = icmp slt i8* %g, %x
63   ret i1 %r
66 define i1 @sgt_base_commute(i64 %y) {
67 ; CHECK-LABEL: @sgt_base_commute(
68 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
69 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, i8* [[X]], i64 [[Y:%.*]]
70 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8* [[X]], [[G]]
71 ; CHECK-NEXT:    ret i1 [[R]]
73   %x = call i8* @getptr() ; thwart complexity-based canonicalization
74   %g = getelementptr i8, i8* %x, i64 %y
75   %r = icmp sgt i8* %x, %g
76   ret i1 %r
79 define i1 @slt_base_inbounds(i8* %x, i64 %y) {
80 ; CHECK-LABEL: @slt_base_inbounds(
81 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i64 [[Y:%.*]]
82 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i8* [[G]], [[X]]
83 ; CHECK-NEXT:    ret i1 [[R]]
85   %g = getelementptr inbounds i8, i8* %x, i64 %y
86   %r = icmp slt i8* %g, %x
87   ret i1 %r
90 define i1 @sgt_base_inbounds_commute(i64 %y) {
91 ; CHECK-LABEL: @sgt_base_inbounds_commute(
92 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
93 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, i8* [[X]], i64 [[Y:%.*]]
94 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8* [[X]], [[G]]
95 ; CHECK-NEXT:    ret i1 [[R]]
97   %x = call i8* @getptr() ; thwart complexity-based canonicalization
98   %g = getelementptr inbounds i8, i8* %x, i64 %y
99   %r = icmp sgt i8* %x, %g
100   ret i1 %r
103 define i1 @ult_base(i8* %x, i64 %y) {
104 ; CHECK-LABEL: @ult_base(
105 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, i8* [[X:%.*]], i64 [[Y:%.*]]
106 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8* [[G]], [[X]]
107 ; CHECK-NEXT:    ret i1 [[R]]
109   %g = getelementptr i8, i8* %x, i64 %y
110   %r = icmp ult i8* %g, %x
111   ret i1 %r
114 define i1 @ugt_base_commute(i64 %y) {
115 ; CHECK-LABEL: @ugt_base_commute(
116 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
117 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, i8* [[X]], i64 [[Y:%.*]]
118 ; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8* [[X]], [[G]]
119 ; CHECK-NEXT:    ret i1 [[R]]
121   %x = call i8* @getptr() ; thwart complexity-based canonicalization
122   %g = getelementptr i8, i8* %x, i64 %y
123   %r = icmp ugt i8* %x, %g
124   ret i1 %r
127 define i1 @ult_base_inbounds(i8* %x, i64 %y) {
128 ; CHECK-LABEL: @ult_base_inbounds(
129 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0
130 ; CHECK-NEXT:    ret i1 [[R]]
132   %g = getelementptr inbounds i8, i8* %x, i64 %y
133   %r = icmp ult i8* %g, %x
134   ret i1 %r
137 define i1 @ugt_base_inbounds_commute(i64 %y) {
138 ; CHECK-LABEL: @ugt_base_inbounds_commute(
139 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
140 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0
141 ; CHECK-NEXT:    ret i1 [[R]]
143   %x = call i8* @getptr() ; thwart complexity-based canonicalization
144   %g = getelementptr inbounds i8, i8* %x, i64 %y
145   %r = icmp ugt i8* %x, %g
146   ret i1 %r
149 define i1 @ne_base_inbounds_use(i8* %x, i64 %y) {
150 ; CHECK-LABEL: @ne_base_inbounds_use(
151 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i64 [[Y:%.*]]
152 ; CHECK-NEXT:    call void @use(i8* [[G]])
153 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y]], 0
154 ; CHECK-NEXT:    ret i1 [[R]]
156   %g = getelementptr inbounds i8, i8* %x, i64 %y
157   call void @use(i8* %g)
158   %r = icmp ne i8* %g, %x
159   ret i1 %r
162 define i1 @eq_base_inbounds_commute_use(i64 %y) {
163 ; CHECK-LABEL: @eq_base_inbounds_commute_use(
164 ; CHECK-NEXT:    [[X:%.*]] = call i8* @getptr()
165 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, i8* [[X]], i64 [[Y:%.*]]
166 ; CHECK-NEXT:    call void @use(i8* [[G]])
167 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y]], 0
168 ; CHECK-NEXT:    ret i1 [[R]]
170   %x = call i8* @getptr() ; thwart complexity-based canonicalization
171   %g = getelementptr inbounds i8, i8* %x, i64 %y
172   call void @use(i8* %g)
173   %r = icmp eq i8* %x, %g
174   ret i1 %r
177 define i1 @eq_bitcast_base([2 x i8]* %p, i64 %x) {
178 ; CHECK-LABEL: @eq_bitcast_base(
179 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [2 x i8], [2 x i8]* [[P:%.*]], i64 [[X:%.*]], i64 0
180 ; CHECK-NEXT:    [[B:%.*]] = getelementptr [2 x i8], [2 x i8]* [[P]], i64 0, i64 0
181 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i8* [[GEP]], [[B]]
182 ; CHECK-NEXT:    ret i1 [[R]]
184   %gep = getelementptr [2 x i8], [2 x i8]* %p, i64 %x, i64 0
185   %b = bitcast [2 x i8]* %p to i8*
186   %r = icmp eq i8* %gep, %b
187   ret i1 %r
190 define i1 @eq_bitcast_base_inbounds([2 x i8]* %p, i64 %x) {
191 ; CHECK-LABEL: @eq_bitcast_base_inbounds(
192 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[X:%.*]], 0
193 ; CHECK-NEXT:    ret i1 [[R]]
195   %gep = getelementptr inbounds [2 x i8], [2 x i8]* %p, i64 %x, i64 0
196   %b = bitcast [2 x i8]* %p to i8*
197   %r = icmp eq i8* %gep, %b
198   ret i1 %r
201 @X = global [1000 x i32] zeroinitializer
203 define i1 @PR8882(i64 %i) {
204 ; CHECK-LABEL: @PR8882(
205 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000
206 ; CHECK-NEXT:    ret i1 [[CMP]]
208   %p1 = getelementptr inbounds i32, i32* getelementptr inbounds ([1000 x i32], [1000 x i32]* @X, i64 0, i64 0), i64 %i
209   %cmp = icmp eq i32* %p1, getelementptr inbounds ([1000 x i32], [1000 x i32]* @X, i64 1, i64 0)
210   ret i1 %cmp
213 @X_as1 = addrspace(1) global [1000 x i32] zeroinitializer
215 define i1 @test24_as1(i64 %i) {
216 ; CHECK-LABEL: @test24_as1(
217 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16
218 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[TMP1]], 1000
219 ; CHECK-NEXT:    ret i1 [[CMP]]
221   %p1 = getelementptr inbounds i32, i32 addrspace(1)* getelementptr inbounds ([1000 x i32], [1000 x i32] addrspace(1)* @X_as1, i64 0, i64 0), i64 %i
222   %cmp = icmp eq i32 addrspace(1)* %p1, getelementptr inbounds ([1000 x i32], [1000 x i32] addrspace(1)* @X_as1, i64 1, i64 0)
223   ret i1 %cmp
226 ; PR16244
227 define i1 @test71(i8* %x) {
228 ; CHECK-LABEL: @test71(
229 ; CHECK-NEXT:    ret i1 false
231   %a = getelementptr i8, i8* %x, i64 8
232   %b = getelementptr inbounds i8, i8* %x, i64 8
233   %c = icmp ugt i8* %a, %b
234   ret i1 %c
237 define i1 @test71_as1(i8 addrspace(1)* %x) {
238 ; CHECK-LABEL: @test71_as1(
239 ; CHECK-NEXT:    ret i1 false
241   %a = getelementptr i8, i8 addrspace(1)* %x, i64 8
242   %b = getelementptr inbounds i8, i8 addrspace(1)* %x, i64 8
243   %c = icmp ugt i8 addrspace(1)* %a, %b
244   ret i1 %c
247 declare i32 @test58_d(i64)
249 define i1 @test59(i8* %foo) {
250 ; CHECK-LABEL: @test59(
251 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, i8* [[FOO:%.*]], i64 8
252 ; CHECK-NEXT:    [[USE:%.*]] = ptrtoint i8* [[GEP1]] to i64
253 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
254 ; CHECK-NEXT:    ret i1 true
256   %bit = bitcast i8* %foo to i32*
257   %gep1 = getelementptr inbounds i32, i32* %bit, i64 2
258   %gep2 = getelementptr inbounds i8, i8* %foo, i64 10
259   %cast1 = bitcast i32* %gep1 to i8*
260   %cmp = icmp ult i8* %cast1, %gep2
261   %use = ptrtoint i8* %cast1 to i64
262   %call = call i32 @test58_d(i64 %use)
263   ret i1 %cmp
266 define i1 @test59_as1(i8 addrspace(1)* %foo) {
267 ; CHECK-LABEL: @test59_as1(
268 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[FOO:%.*]], i16 8
269 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint i8 addrspace(1)* [[GEP1]] to i16
270 ; CHECK-NEXT:    [[USE:%.*]] = zext i16 [[TMP1]] to i64
271 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
272 ; CHECK-NEXT:    ret i1 true
274   %bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
275   %gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i64 2
276   %gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i64 10
277   %cast1 = bitcast i32 addrspace(1)* %gep1 to i8 addrspace(1)*
278   %cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
279   %use = ptrtoint i8 addrspace(1)* %cast1 to i64
280   %call = call i32 @test58_d(i64 %use)
281   ret i1 %cmp
284 define i1 @test60(i8* %foo, i64 %i, i64 %j) {
285 ; CHECK-LABEL: @test60(
286 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
287 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
288 ; CHECK-NEXT:    ret i1 [[TMP1]]
290   %bit = bitcast i8* %foo to i32*
291   %gep1 = getelementptr inbounds i32, i32* %bit, i64 %i
292   %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
293   %cast1 = bitcast i32* %gep1 to i8*
294   %cmp = icmp ult i8* %cast1, %gep2
295   ret i1 %cmp
298 define i1 @test60_as1(i8 addrspace(1)* %foo, i64 %i, i64 %j) {
299 ; CHECK-LABEL: @test60_as1(
300 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16
301 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16
302 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[TMP1]], 2
303 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]]
304 ; CHECK-NEXT:    ret i1 [[TMP3]]
306   %bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
307   %gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i64 %i
308   %gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i64 %j
309   %cast1 = bitcast i32 addrspace(1)* %gep1 to i8 addrspace(1)*
310   %cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
311   ret i1 %cmp
314 ; Same as test60, but look through an addrspacecast instead of a
315 ; bitcast. This uses the same sized addrspace.
316 define i1 @test60_addrspacecast(i8* %foo, i64 %i, i64 %j) {
317 ; CHECK-LABEL: @test60_addrspacecast(
318 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
319 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
320 ; CHECK-NEXT:    ret i1 [[TMP1]]
322   %bit = addrspacecast i8* %foo to i32 addrspace(3)*
323   %gep1 = getelementptr inbounds i32, i32 addrspace(3)* %bit, i64 %i
324   %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
325   %cast1 = addrspacecast i32 addrspace(3)* %gep1 to i8*
326   %cmp = icmp ult i8* %cast1, %gep2
327   ret i1 %cmp
330 define i1 @test60_addrspacecast_smaller(i8* %foo, i16 %i, i64 %j) {
331 ; CHECK-LABEL: @test60_addrspacecast_smaller(
332 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
333 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16
334 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]
335 ; CHECK-NEXT:    ret i1 [[TMP2]]
337   %bit = addrspacecast i8* %foo to i32 addrspace(1)*
338   %gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i16 %i
339   %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j
340   %cast1 = addrspacecast i32 addrspace(1)* %gep1 to i8*
341   %cmp = icmp ult i8* %cast1, %gep2
342   ret i1 %cmp
345 define i1 @test60_addrspacecast_larger(i8 addrspace(1)* %foo, i32 %i, i16 %j) {
346 ; CHECK-LABEL: @test60_addrspacecast_larger(
347 ; CHECK-NEXT:    [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16
348 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i16 [[I_TR]], 2
349 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i16 [[TMP1]], [[J:%.*]]
350 ; CHECK-NEXT:    ret i1 [[TMP2]]
352   %bit = addrspacecast i8 addrspace(1)* %foo to i32 addrspace(2)*
353   %gep1 = getelementptr inbounds i32, i32 addrspace(2)* %bit, i32 %i
354   %gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i16 %j
355   %cast1 = addrspacecast i32 addrspace(2)* %gep1 to i8 addrspace(1)*
356   %cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
357   ret i1 %cmp
360 define i1 @test61(i8* %foo, i64 %i, i64 %j) {
361 ; CHECK-LABEL: @test61(
362 ; CHECK-NEXT:    [[BIT:%.*]] = bitcast i8* [[FOO:%.*]] to i32*
363 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, i32* [[BIT]], i64 [[I:%.*]]
364 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, i8* [[FOO]], i64 [[J:%.*]]
365 ; CHECK-NEXT:    [[CAST1:%.*]] = bitcast i32* [[GEP1]] to i8*
366 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8* [[GEP2]], [[CAST1]]
367 ; CHECK-NEXT:    ret i1 [[CMP]]
369   %bit = bitcast i8* %foo to i32*
370   %gep1 = getelementptr i32, i32* %bit, i64 %i
371   %gep2 = getelementptr  i8,  i8* %foo, i64 %j
372   %cast1 = bitcast i32* %gep1 to i8*
373   %cmp = icmp ult i8* %cast1, %gep2
374   ret i1 %cmp
375 ; Don't transform non-inbounds GEPs.
378 define i1 @test61_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
379 ; CHECK-LABEL: @test61_as1(
380 ; CHECK-NEXT:    [[BIT:%.*]] = bitcast i8 addrspace(1)* [[FOO:%.*]] to i32 addrspace(1)*
381 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, i32 addrspace(1)* [[BIT]], i16 [[I:%.*]]
382 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, i8 addrspace(1)* [[FOO]], i16 [[J:%.*]]
383 ; CHECK-NEXT:    [[CAST1:%.*]] = bitcast i32 addrspace(1)* [[GEP1]] to i8 addrspace(1)*
384 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 addrspace(1)* [[GEP2]], [[CAST1]]
385 ; CHECK-NEXT:    ret i1 [[CMP]]
387   %bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
388   %gep1 = getelementptr i32, i32 addrspace(1)* %bit, i16 %i
389   %gep2 = getelementptr i8, i8 addrspace(1)* %foo, i16 %j
390   %cast1 = bitcast i32 addrspace(1)* %gep1 to i8 addrspace(1)*
391   %cmp = icmp ult i8 addrspace(1)* %cast1, %gep2
392   ret i1 %cmp
393 ; Don't transform non-inbounds GEPs.