[SLP] Add cost model for `llvm.powi.*` intrinsics
[llvm-project.git] / llvm / test / Transforms / InstCombine / compare-alloca.ll
blob6201b346126dcbcdcd63855d25215f80dd8f5a30
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S %s | FileCheck %s
3 target datalayout = "p:32:32"
6 define i1 @alloca_argument_compare(i64* %arg) {
7 ; CHECK-LABEL: @alloca_argument_compare(
8 ; CHECK-NEXT:    ret i1 false
10   %alloc = alloca i64
11   %cmp = icmp eq i64* %arg, %alloc
12   ret i1 %cmp
15 define i1 @alloca_argument_compare_swapped(i64* %arg) {
16 ; CHECK-LABEL: @alloca_argument_compare_swapped(
17 ; CHECK-NEXT:    ret i1 false
19   %alloc = alloca i64
20   %cmp = icmp eq i64* %alloc, %arg
21   ret i1 %cmp
24 define i1 @alloca_argument_compare_ne(i64* %arg) {
25 ; CHECK-LABEL: @alloca_argument_compare_ne(
26 ; CHECK-NEXT:    ret i1 true
28   %alloc = alloca i64
29   %cmp = icmp ne i64* %arg, %alloc
30   ret i1 %cmp
33 define i1 @alloca_argument_compare_derived_ptrs(i64* %arg, i64 %x) {
34 ; CHECK-LABEL: @alloca_argument_compare_derived_ptrs(
35 ; CHECK-NEXT:    ret i1 false
37   %alloc = alloca i64, i64 8
38   %p = getelementptr i64, i64* %arg, i64 %x
39   %q = getelementptr i64, i64* %alloc, i64 3
40   %cmp = icmp eq i64* %p, %q
41   ret i1 %cmp
44 declare void @escape(i64*)
45 define i1 @alloca_argument_compare_escaped_alloca(i64* %arg) {
46 ; CHECK-LABEL: @alloca_argument_compare_escaped_alloca(
47 ; CHECK-NEXT:    [[ALLOC:%.*]] = alloca i64, align 8
48 ; CHECK-NEXT:    call void @escape(i64* nonnull [[ALLOC]])
49 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64* [[ALLOC]], [[ARG:%.*]]
50 ; CHECK-NEXT:    ret i1 [[CMP]]
52   %alloc = alloca i64
53   call void @escape(i64* %alloc)
54   %cmp = icmp eq i64* %alloc, %arg
55   ret i1 %cmp
58 declare void @check_compares(i1, i1)
59 define void @alloca_argument_compare_two_compares(i64* %p) {
60 ; CHECK-LABEL: @alloca_argument_compare_two_compares(
61 ; CHECK-NEXT:    [[Q1:%.*]] = alloca [8 x i64], align 8
62 ; CHECK-NEXT:    [[Q1_SUB:%.*]] = getelementptr inbounds [8 x i64], [8 x i64]* [[Q1]], i32 0, i32 0
63 ; CHECK-NEXT:    [[R:%.*]] = getelementptr i64, i64* [[P:%.*]], i32 1
64 ; CHECK-NEXT:    [[S:%.*]] = getelementptr inbounds [8 x i64], [8 x i64]* [[Q1]], i32 0, i32 2
65 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i64* [[Q1_SUB]], [[P]]
66 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i64* [[R]], [[S]]
67 ; CHECK-NEXT:    call void @check_compares(i1 [[CMP1]], i1 [[CMP2]])
68 ; CHECK-NEXT:    ret void
70   %q = alloca i64, i64 8
71   %r = getelementptr i64, i64* %p, i64 1
72   %s = getelementptr i64, i64* %q, i64 2
73   %cmp1 = icmp eq i64* %p, %q
74   %cmp2 = icmp eq i64* %r, %s
75   call void @check_compares(i1 %cmp1, i1 %cmp2)
76   ret void
77   ; We will only fold if there is a single cmp.
80 define i1 @alloca_argument_compare_escaped_through_store(i64* %arg, i64** %ptr) {
81 ; CHECK-LABEL: @alloca_argument_compare_escaped_through_store(
82 ; CHECK-NEXT:    [[ALLOC:%.*]] = alloca i64, align 8
83 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64* [[ALLOC]], [[ARG:%.*]]
84 ; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds i64, i64* [[ALLOC]], i32 1
85 ; CHECK-NEXT:    store i64* [[P]], i64** [[PTR:%.*]], align 4
86 ; CHECK-NEXT:    ret i1 [[CMP]]
88   %alloc = alloca i64
89   %cmp = icmp eq i64* %alloc, %arg
90   %p = getelementptr i64, i64* %alloc, i64 1
91   store i64* %p, i64** %ptr
92   ret i1 %cmp
95 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
96 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
97 define i1 @alloca_argument_compare_benign_instrs(i8* %arg) {
98 ; CHECK-LABEL: @alloca_argument_compare_benign_instrs(
99 ; CHECK-NEXT:    ret i1 false
101   %alloc = alloca i8
102   call void @llvm.lifetime.start.p0i8(i64 1, i8* %alloc)
103   %cmp = icmp eq i8* %arg, %alloc
104   %x = load i8, i8* %arg
105   store i8 %x, i8* %alloc
106   call void @llvm.lifetime.end.p0i8(i64 1, i8* %alloc)
107   ret i1 %cmp
110 declare i64* @allocator()
111 define i1 @alloca_call_compare() {
112 ; CHECK-LABEL: @alloca_call_compare(
113 ; CHECK-NEXT:    [[Q:%.*]] = call i64* @allocator()
114 ; CHECK-NEXT:    ret i1 false
116   %p = alloca i64
117   %q = call i64* @allocator()
118   %cmp = icmp eq i64* %p, %q
119   ret i1 %cmp
123 ; The next block of tests demonstrate a very subtle correctness requirement.
124 ; We can generally assume any *single* stack layout we chose for the result of
125 ; an alloca, but we can't simultanious assume two different ones.  As a
126 ; result, we must make sure that we only fold conditions if we can ensure that
127 ; we fold *all* potentially address capturing compares the same.
129 ; These two functions represents either a) forging a pointer via inttoptr or
130 ; b) indexing off an adjacent allocation.  In either case, the operation is
131 ; obscured by an uninlined helper and not visible to instcombine.
132 declare i8* @hidden_inttoptr()
133 declare i8* @hidden_offset(i8* %other)
135 define i1 @ptrtoint_single_cmp() {
136 ; CHECK-LABEL: @ptrtoint_single_cmp(
137 ; CHECK-NEXT:    ret i1 false
139   %m = alloca i8, i32 4
140   %rhs = inttoptr i64 2048 to i8*
141   %cmp = icmp eq i8* %m, %rhs
142   ret i1 %cmp
145 define i1 @offset_single_cmp() {
146 ; CHECK-LABEL: @offset_single_cmp(
147 ; CHECK-NEXT:    ret i1 false
149   %m = alloca i8, i32 4
150   %n = alloca i8, i32 4
151   %rhs = getelementptr i8, i8* %n, i32 4
152   %cmp = icmp eq i8* %m, %rhs
153   ret i1 %cmp
156 declare void @witness(i1, i1)
158 define void @neg_consistent_fold1() {
159 ; CHECK-LABEL: @neg_consistent_fold1(
160 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
161 ; CHECK-NEXT:    [[M1_SUB:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[M1]], i32 0, i32 0
162 ; CHECK-NEXT:    [[RHS2:%.*]] = call i8* @hidden_inttoptr()
163 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8* [[M1_SUB]], inttoptr (i64 2048 to i8*)
164 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8* [[M1_SUB]], [[RHS2]]
165 ; CHECK-NEXT:    call void @witness(i1 [[CMP1]], i1 [[CMP2]])
166 ; CHECK-NEXT:    ret void
168   %m = alloca i8, i32 4
169   %rhs = inttoptr i64 2048 to i8*
170   %rhs2 = call i8* @hidden_inttoptr()
171   %cmp1 = icmp eq i8* %m, %rhs
172   %cmp2 = icmp eq i8* %m, %rhs2
173   call void @witness(i1 %cmp1, i1 %cmp2)
174   ret void
177 define void @neg_consistent_fold2() {
178 ; CHECK-LABEL: @neg_consistent_fold2(
179 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
180 ; CHECK-NEXT:    [[N2:%.*]] = alloca [4 x i8], align 1
181 ; CHECK-NEXT:    [[N2_SUB:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[N2]], i32 0, i32 0
182 ; CHECK-NEXT:    [[M1_SUB:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[M1]], i32 0, i32 0
183 ; CHECK-NEXT:    [[RHS:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[N2]], i32 0, i32 4
184 ; CHECK-NEXT:    [[RHS2:%.*]] = call i8* @hidden_offset(i8* nonnull [[N2_SUB]])
185 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8* [[M1_SUB]], [[RHS]]
186 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8* [[M1_SUB]], [[RHS2]]
187 ; CHECK-NEXT:    call void @witness(i1 [[CMP1]], i1 [[CMP2]])
188 ; CHECK-NEXT:    ret void
190   %m = alloca i8, i32 4
191   %n = alloca i8, i32 4
192   %rhs = getelementptr i8, i8* %n, i32 4
193   %rhs2 = call i8* @hidden_offset(i8* %n)
194   %cmp1 = icmp eq i8* %m, %rhs
195   %cmp2 = icmp eq i8* %m, %rhs2
196   call void @witness(i1 %cmp1, i1 %cmp2)
197   ret void
200 define void @neg_consistent_fold3() {
201 ; CHECK-LABEL: @neg_consistent_fold3(
202 ; CHECK-NEXT:    [[M1:%.*]] = alloca i32, align 1
203 ; CHECK-NEXT:    [[M1_SUB:%.*]] = bitcast i32* [[M1]] to i8*
204 ; CHECK-NEXT:    [[LGP:%.*]] = load i32*, i32** @gp, align 8
205 ; CHECK-NEXT:    [[RHS2:%.*]] = call i8* @hidden_inttoptr()
206 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32* [[M1]], [[LGP]]
207 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8* [[RHS2]], [[M1_SUB]]
208 ; CHECK-NEXT:    call void @witness(i1 [[CMP1]], i1 [[CMP2]])
209 ; CHECK-NEXT:    ret void
211   %m = alloca i8, i32 4
212   %bc = bitcast i8* %m to i32*
213   %lgp = load i32*, i32** @gp, align 8
214   %rhs2 = call i8* @hidden_inttoptr()
215   %cmp1 = icmp eq i32* %bc, %lgp
216   %cmp2 = icmp eq i8* %m, %rhs2
217   call void @witness(i1 %cmp1, i1 %cmp2)
218   ret void
221 define void @neg_consistent_fold4() {
222 ; CHECK-LABEL: @neg_consistent_fold4(
223 ; CHECK-NEXT:    call void @witness(i1 false, i1 false)
224 ; CHECK-NEXT:    ret void
226   %m = alloca i8, i32 4
227   %bc = bitcast i8* %m to i32*
228   %lgp = load i32*, i32** @gp, align 8
229   %cmp1 = icmp eq i32* %bc, %lgp
230   %cmp2 = icmp eq i32* %bc, %lgp
231   call void @witness(i1 %cmp1, i1 %cmp2)
232   ret void
235 ; A nocapture call can't cause a consistent result issue as it is (by
236 ; assumption) not able to contain a comparison which might capture the
237 ; address.
239 declare void @unknown(i8*)
241 ; TODO: Missing optimization
242 define i1 @consistent_nocapture_inttoptr() {
243 ; CHECK-LABEL: @consistent_nocapture_inttoptr(
244 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
245 ; CHECK-NEXT:    [[M1_SUB:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[M1]], i32 0, i32 0
246 ; CHECK-NEXT:    call void @unknown(i8* nocapture nonnull [[M1_SUB]])
247 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[M1_SUB]], inttoptr (i64 2048 to i8*)
248 ; CHECK-NEXT:    ret i1 [[CMP]]
250   %m = alloca i8, i32 4
251   call void @unknown(i8* nocapture %m)
252   %rhs = inttoptr i64 2048 to i8*
253   %cmp = icmp eq i8* %m, %rhs
254   ret i1 %cmp
257 define i1 @consistent_nocapture_offset() {
258 ; CHECK-LABEL: @consistent_nocapture_offset(
259 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
260 ; CHECK-NEXT:    [[M1_SUB:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[M1]], i32 0, i32 0
261 ; CHECK-NEXT:    call void @unknown(i8* nocapture nonnull [[M1_SUB]])
262 ; CHECK-NEXT:    ret i1 false
264   %m = alloca i8, i32 4
265   call void @unknown(i8* nocapture %m)
266   %n = alloca i8, i32 4
267   %rhs = getelementptr i8, i8* %n, i32 4
268   %cmp = icmp eq i8* %m, %rhs
269   ret i1 %cmp
272 @gp = global i32* null, align 8
273 ; TODO: Missing optimization
274 define i1 @consistent_nocapture_through_global() {
275 ; CHECK-LABEL: @consistent_nocapture_through_global(
276 ; CHECK-NEXT:    [[M1:%.*]] = alloca i32, align 1
277 ; CHECK-NEXT:    [[M1_SUB:%.*]] = bitcast i32* [[M1]] to i8*
278 ; CHECK-NEXT:    call void @unknown(i8* nocapture nonnull [[M1_SUB]])
279 ; CHECK-NEXT:    [[LGP:%.*]] = load i32*, i32** @gp, align 8, !nonnull !0
280 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32* [[M1]], [[LGP]]
281 ; CHECK-NEXT:    ret i1 [[CMP]]
283   %m = alloca i8, i32 4
284   call void @unknown(i8* nocapture %m)
285   %bc = bitcast i8* %m to i32*
286   %lgp = load i32*, i32** @gp, align 8, !nonnull !{}
287   %cmp = icmp eq i32* %bc, %lgp
288   ret i1 %cmp