[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / InstCombine / indexed-gep-compares.ll
blobc00fd5be06e477afcc7c2a1d8cfb28a5217dc9a3
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:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64"
6 define i32 *@test1(i32* %A, i32 %Offset) {
7 ; CHECK-LABEL: @test1(
8 ; CHECK-NEXT:  entry:
9 ; CHECK-NEXT:    br label [[BB:%.*]]
10 ; CHECK:       bb:
11 ; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
12 ; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
13 ; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
14 ; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
15 ; CHECK:       bb2:
16 ; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[RHS_IDX]]
17 ; CHECK-NEXT:    ret i32* [[RHS_PTR]]
19 entry:
20   %tmp = getelementptr inbounds i32, i32* %A, i32 %Offset
21   br label %bb
23 bb:
24   %RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
25   %LHS = getelementptr inbounds i32, i32* %A, i32 100
26   %RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
27   %cond = icmp ult i32 * %LHS, %RHS
28   br i1 %cond, label %bb2, label %bb
30 bb2:
31   ret i32* %RHS
34 define i32 *@test2(i32 %A, i32 %Offset) {
35 ; CHECK-LABEL: @test2(
36 ; CHECK-NEXT:  entry:
37 ; CHECK-NEXT:    br label [[BB:%.*]]
38 ; CHECK:       bb:
39 ; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
40 ; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
41 ; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
42 ; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
43 ; CHECK:       bb2:
44 ; CHECK-NEXT:    [[RHSTO_PTR:%.*]] = inttoptr i32 [[A:%.*]] to i32*
45 ; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i32, i32* [[RHSTO_PTR]], i32 [[RHS_IDX]]
46 ; CHECK-NEXT:    ret i32* [[RHS_PTR]]
48 entry:
49   %A.ptr = inttoptr i32 %A to i32*
50   %tmp = getelementptr inbounds i32, i32* %A.ptr, i32 %Offset
51   br label %bb
53 bb:
54   %RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
55   %LHS = getelementptr inbounds i32, i32* %A.ptr, i32 100
56   %RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
57   %cmp0 = ptrtoint i32 *%LHS to i32
58   %cmp1 = ptrtoint i32 *%RHS to i32
59   %cond = icmp ult i32 %cmp0, %cmp1
60   br i1 %cond, label %bb2, label %bb
62 bb2:
63   ret i32* %RHS
66 ; Perform the transformation only if we know that the GEPs used are inbounds.
67 define i32 *@test3(i32* %A, i32 %Offset) {
68 ; CHECK-LABEL: @test3(
69 ; CHECK-NEXT:  entry:
70 ; CHECK-NEXT:    [[TMP:%.*]] = getelementptr i32, i32* [[A:%.*]], i32 [[OFFSET:%.*]]
71 ; CHECK-NEXT:    br label [[BB:%.*]]
72 ; CHECK:       bb:
73 ; CHECK-NEXT:    [[RHS:%.*]] = phi i32* [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
74 ; CHECK-NEXT:    [[LHS:%.*]] = getelementptr i32, i32* [[A]], i32 100
75 ; CHECK-NEXT:    [[RHS_NEXT]] = getelementptr i32, i32* [[RHS]], i32 1
76 ; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32* [[LHS]], [[RHS]]
77 ; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
78 ; CHECK:       bb2:
79 ; CHECK-NEXT:    ret i32* [[RHS]]
81 entry:
82   %tmp = getelementptr i32, i32* %A, i32 %Offset
83   br label %bb
85 bb:
86   %RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
87   %LHS = getelementptr i32, i32* %A, i32 100
88   %RHS.next = getelementptr i32, i32* %RHS, i64 1
89   %cond = icmp ult i32 * %LHS, %RHS
90   br i1 %cond, label %bb2, label %bb
92 bb2:
93   ret i32* %RHS
96 ; An inttoptr that requires an extension or truncation will be opaque when determining
97 ; the base pointer. In this case we can still perform the transformation by considering
98 ; A.ptr as being the base pointer.
99 define i32 *@test4(i16 %A, i32 %Offset) {
100 ; CHECK-LABEL: @test4(
101 ; CHECK-NEXT:  entry:
102 ; CHECK-NEXT:    br label [[BB:%.*]]
103 ; CHECK:       bb:
104 ; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
105 ; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
106 ; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
107 ; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
108 ; CHECK:       bb2:
109 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[A:%.*]] to i32
110 ; CHECK-NEXT:    [[RHSTO_PTR:%.*]] = inttoptr i32 [[TMP0]] to i32*
111 ; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i32, i32* [[RHSTO_PTR]], i32 [[RHS_IDX]]
112 ; CHECK-NEXT:    ret i32* [[RHS_PTR]]
114 entry:
115   %A.ptr = inttoptr i16 %A to i32*
116   %tmp = getelementptr inbounds i32, i32* %A.ptr, i32 %Offset
117   br label %bb
120   %RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
121   %LHS = getelementptr inbounds i32, i32* %A.ptr, i32 100
122   %RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
123   %cmp0 = ptrtoint i32 *%LHS to i32
124   %cmp1 = ptrtoint i32 *%RHS to i32
125   %cond = icmp ult i32 %cmp0, %cmp1
126   br i1 %cond, label %bb2, label %bb
128 bb2:
129   ret i32* %RHS
132 declare i32* @fun_ptr()
134 define i32 *@test5(i32 %Offset) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
135 ; CHECK-LABEL: @test5(
136 ; CHECK-NEXT:  entry:
137 ; CHECK-NEXT:    [[A:%.*]] = invoke i32* @fun_ptr()
138 ; CHECK-NEXT:    to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
139 ; CHECK:       cont:
140 ; CHECK-NEXT:    br label [[BB:%.*]]
141 ; CHECK:       bb:
142 ; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[CONT]] ]
143 ; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
144 ; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
145 ; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
146 ; CHECK:       bb2:
147 ; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[RHS_IDX]]
148 ; CHECK-NEXT:    ret i32* [[RHS_PTR]]
149 ; CHECK:       lpad:
150 ; CHECK-NEXT:    [[L:%.*]] = landingpad { i8*, i32 }
151 ; CHECK-NEXT:    cleanup
152 ; CHECK-NEXT:    ret i32* null
154 entry:
155   %A = invoke i32 *@fun_ptr() to label %cont unwind label %lpad
157 cont:
158   %tmp = getelementptr inbounds i32, i32* %A, i32 %Offset
159   br label %bb
162   %RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %cont ]
163   %LHS = getelementptr inbounds i32, i32* %A, i32 100
164   %RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
165   %cond = icmp ult i32 * %LHS, %RHS
166   br i1 %cond, label %bb2, label %bb
168 bb2:
169   ret i32* %RHS
171 lpad:
172   %l = landingpad { i8*, i32 } cleanup
173   ret i32* null
176 declare i32 @fun_i32()
178 define i32 *@test6(i32 %Offset) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
179 ; CHECK-LABEL: @test6(
180 ; CHECK-NEXT:  entry:
181 ; CHECK-NEXT:    [[A:%.*]] = invoke i32 @fun_i32()
182 ; CHECK-NEXT:    to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
183 ; CHECK:       cont:
184 ; CHECK-NEXT:    br label [[BB:%.*]]
185 ; CHECK:       bb:
186 ; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[CONT]] ]
187 ; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
188 ; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
189 ; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
190 ; CHECK:       bb2:
191 ; CHECK-NEXT:    [[RHSTO_PTR:%.*]] = inttoptr i32 [[A]] to i32*
192 ; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i32, i32* [[RHSTO_PTR]], i32 [[RHS_IDX]]
193 ; CHECK-NEXT:    ret i32* [[RHS_PTR]]
194 ; CHECK:       lpad:
195 ; CHECK-NEXT:    [[L:%.*]] = landingpad { i8*, i32 }
196 ; CHECK-NEXT:    cleanup
197 ; CHECK-NEXT:    ret i32* null
199 entry:
200   %A = invoke i32 @fun_i32() to label %cont unwind label %lpad
202 cont:
203   %A.ptr = inttoptr i32 %A to i32*
204   %tmp = getelementptr inbounds i32, i32* %A.ptr, i32 %Offset
205   br label %bb
208   %RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %cont ]
209   %LHS = getelementptr inbounds i32, i32* %A.ptr, i32 100
210   %RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
211   %cond = icmp ult i32 * %LHS, %RHS
212   br i1 %cond, label %bb2, label %bb
214 bb2:
215   ret i32* %RHS
217 lpad:
218   %l = landingpad { i8*, i32 } cleanup
219   ret i32* null
223 @pr30402 = constant i64 3
224 define i1 @test7() {
225 ; CHECK-LABEL: @test7(
226 ; CHECK-NEXT:  entry:
227 ; CHECK-NEXT:    br label [[BB7:%.*]]
228 ; CHECK:       bb7:
229 ; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, [[BB7]] ], [ false, [[ENTRY:%.*]] ]
230 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB10:%.*]], label [[BB7]]
231 ; CHECK:       bb10:
232 ; CHECK-NEXT:    ret i1 [[CMP]]
234 entry:
235   br label %bb7
237 bb7:                                              ; preds = %bb10, %entry-block
238   %phi = phi i64* [ @pr30402, %entry ], [ getelementptr inbounds (i64, i64* @pr30402, i32 1), %bb7 ]
239   %cmp = icmp eq i64* %phi, getelementptr inbounds (i64, i64* @pr30402, i32 1)
240   br i1 %cmp, label %bb10, label %bb7
242 bb10:
243   ret i1 %cmp
246 ; It is not generally safe to hoist an expression (sdiv) that may trap.
248 define i1 @PR50906() {
249 ; CHECK-LABEL: @PR50906(
250 ; CHECK-NEXT:  entry:
251 ; CHECK-NEXT:    br label [[LOOP:%.*]]
252 ; CHECK:       loop:
253 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[NEXT:%.*]] ]
254 ; CHECK-NEXT:    br label [[NEXT]]
255 ; CHECK:       next:
256 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[PHI]], sdiv (i32 7, i32 ptrtoint (i1 ()* @PR50906 to i32))
257 ; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
258 ; CHECK:       exit:
259 ; CHECK-NEXT:    ret i1 [[CMP]]
261 entry:
262   br label %loop
264 loop:
265   %phi = phi i32 [ 0, %entry ], [ 1, %next ]
266   br label %next
268 next:
269   %cmp = icmp sgt i32 sdiv (i32 7, i32 ptrtoint (i1 ()* @PR50906 to i32)), %phi
270   br i1 %cmp, label %exit, label %loop
272 exit:
273   ret i1 %cmp
276 declare i32 @__gxx_personality_v0(...)
278 define i1 @test8(i64* %in, i64 %offset) {
279 ; CHECK-LABEL: @test8(
280 ; CHECK-NEXT:  entry:
281 ; CHECK-NEXT:    [[LD:%.*]] = load i64, i64* [[IN:%.*]], align 8
282 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[LD]] to i32
283 ; CHECK-NEXT:    [[CASTI8:%.*]] = inttoptr i32 [[TMP0]] to i8*
284 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[OFFSET:%.*]] to i32
285 ; CHECK-NEXT:    [[GEPI8:%.*]] = getelementptr inbounds i8, i8* [[CASTI8]], i32 [[TMP1]]
286 ; CHECK-NEXT:    [[CAST:%.*]] = bitcast i8* [[GEPI8]] to i32**
287 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[LD]] to i32
288 ; CHECK-NEXT:    [[PTRCAST:%.*]] = inttoptr i32 [[TMP2]] to i32**
289 ; CHECK-NEXT:    [[GEPI32:%.*]] = getelementptr inbounds i32*, i32** [[PTRCAST]], i32 1
290 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32** [[GEPI32]], [[CAST]]
291 ; CHECK-NEXT:    ret i1 [[CMP]]
293 entry:
294   %ld = load i64, i64* %in, align 8
295   %casti8 = inttoptr i64 %ld to i8*
296   %gepi8 = getelementptr inbounds i8, i8* %casti8, i64 %offset
297   %cast = bitcast i8* %gepi8 to i32**
298   %ptrcast = inttoptr i64 %ld to i32**
299   %gepi32 = getelementptr inbounds i32*, i32** %ptrcast, i64 1
300   %cmp = icmp eq i32** %gepi32, %cast
301   ret i1 %cmp
304 define void @test_zero_offset_cycle({ i64, i64 }* %arg) {
305 ; CHECK-LABEL: @test_zero_offset_cycle(
306 ; CHECK-NEXT:  entry:
307 ; CHECK-NEXT:    br label [[LOOP:%.*]]
308 ; CHECK:       loop:
309 ; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[LOOP_CONT:%.*]]
310 ; CHECK:       loop.cont:
311 ; CHECK-NEXT:    br label [[LOOP]]
313 entry:
314   %gep = getelementptr inbounds { i64, i64 }, { i64, i64 }* %arg, i32 0, i32 1
315   %gep.int = ptrtoint i64* %gep to i32
316   br label %loop
318 loop:
319   %phi = phi i32 [ %gep.int, %entry ], [ %gep.int2, %loop.cont ], [ %phi, %loop ]
320   %phi.ptr = inttoptr i32 %phi to i64*
321   %cmp = icmp eq i64* %gep, %phi.ptr
322   br i1 %cmp, label %loop, label %loop.cont
324 loop.cont:
325   %gep.int2 = ptrtoint i64* %gep to i32
326   br label %loop