[clang][Driver] Support simplified triple versions for config files (#111387)
[llvm-project.git] / llvm / test / Transforms / InstCombine / compare-alloca.ll
blobe6342520c6fa9a0aceb46389d2d66f2859ce7594
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(ptr %arg) {
7 ; CHECK-LABEL: @alloca_argument_compare(
8 ; CHECK-NEXT:    ret i1 false
10   %alloc = alloca i64
11   %cmp = icmp eq ptr %arg, %alloc
12   ret i1 %cmp
15 define i1 @alloca_argument_compare_swapped(ptr %arg) {
16 ; CHECK-LABEL: @alloca_argument_compare_swapped(
17 ; CHECK-NEXT:    ret i1 false
19   %alloc = alloca i64
20   %cmp = icmp eq ptr %alloc, %arg
21   ret i1 %cmp
24 define i1 @alloca_argument_compare_ne(ptr %arg) {
25 ; CHECK-LABEL: @alloca_argument_compare_ne(
26 ; CHECK-NEXT:    ret i1 true
28   %alloc = alloca i64
29   %cmp = icmp ne ptr %arg, %alloc
30   ret i1 %cmp
33 define i1 @alloca_argument_compare_derived_ptrs(ptr %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, ptr %arg, i64 %x
39   %q = getelementptr i64, ptr %alloc, i64 3
40   %cmp = icmp eq ptr %p, %q
41   ret i1 %cmp
44 declare void @escape(ptr)
45 define i1 @alloca_argument_compare_escaped_alloca(ptr %arg) {
46 ; CHECK-LABEL: @alloca_argument_compare_escaped_alloca(
47 ; CHECK-NEXT:    [[ALLOC:%.*]] = alloca i64, align 8
48 ; CHECK-NEXT:    call void @escape(ptr nonnull [[ALLOC]])
49 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ALLOC]], [[ARG:%.*]]
50 ; CHECK-NEXT:    ret i1 [[CMP]]
52   %alloc = alloca i64
53   call void @escape(ptr %alloc)
54   %cmp = icmp eq ptr %alloc, %arg
55   ret i1 %cmp
58 declare void @check_compares(i1, i1)
59 define void @alloca_argument_compare_two_compares(ptr %p) {
60 ; CHECK-LABEL: @alloca_argument_compare_two_compares(
61 ; CHECK-NEXT:    call void @check_compares(i1 false, i1 false)
62 ; CHECK-NEXT:    ret void
64   %q = alloca i64, i64 8
65   %r = getelementptr i64, ptr %p, i64 1
66   %s = getelementptr i64, ptr %q, i64 2
67   %cmp1 = icmp eq ptr %p, %q
68   %cmp2 = icmp eq ptr %r, %s
69   call void @check_compares(i1 %cmp1, i1 %cmp2)
70   ret void
71   ; We will only fold if there is a single cmp.
74 define i1 @alloca_argument_compare_escaped_through_store(ptr %arg, ptr %ptr) {
75 ; CHECK-LABEL: @alloca_argument_compare_escaped_through_store(
76 ; CHECK-NEXT:    [[ALLOC:%.*]] = alloca i64, align 8
77 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ALLOC]], [[ARG:%.*]]
78 ; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds nuw i8, ptr [[ALLOC]], i32 8
79 ; CHECK-NEXT:    store ptr [[P]], ptr [[PTR:%.*]], align 4
80 ; CHECK-NEXT:    ret i1 [[CMP]]
82   %alloc = alloca i64
83   %cmp = icmp eq ptr %alloc, %arg
84   %p = getelementptr i64, ptr %alloc, i64 1
85   store ptr %p, ptr %ptr
86   ret i1 %cmp
89 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
90 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
91 define i1 @alloca_argument_compare_benign_instrs(ptr %arg) {
92 ; CHECK-LABEL: @alloca_argument_compare_benign_instrs(
93 ; CHECK-NEXT:    ret i1 false
95   %alloc = alloca i8
96   call void @llvm.lifetime.start.p0(i64 1, ptr %alloc)
97   %cmp = icmp eq ptr %arg, %alloc
98   %x = load i8, ptr %arg
99   store i8 %x, ptr %alloc
100   call void @llvm.lifetime.end.p0(i64 1, ptr %alloc)
101   ret i1 %cmp
104 declare ptr @allocator()
105 define i1 @alloca_call_compare() {
106 ; CHECK-LABEL: @alloca_call_compare(
107 ; CHECK-NEXT:    [[Q:%.*]] = call ptr @allocator()
108 ; CHECK-NEXT:    ret i1 false
110   %p = alloca i64
111   %q = call ptr @allocator()
112   %cmp = icmp eq ptr %p, %q
113   ret i1 %cmp
117 ; The next block of tests demonstrate a very subtle correctness requirement.
118 ; We can generally assume any *single* stack layout we chose for the result of
119 ; an alloca, but we can't simultanious assume two different ones.  As a
120 ; result, we must make sure that we only fold conditions if we can ensure that
121 ; we fold *all* potentially address capturing compares the same.
123 ; These two functions represents either a) forging a pointer via inttoptr or
124 ; b) indexing off an adjacent allocation.  In either case, the operation is
125 ; obscured by an uninlined helper and not visible to instcombine.
126 declare ptr @hidden_inttoptr()
127 declare ptr @hidden_offset(ptr %other)
129 define i1 @ptrtoint_single_cmp() {
130 ; CHECK-LABEL: @ptrtoint_single_cmp(
131 ; CHECK-NEXT:    ret i1 false
133   %m = alloca i8, i32 4
134   %rhs = inttoptr i64 2048 to ptr
135   %cmp = icmp eq ptr %m, %rhs
136   ret i1 %cmp
139 define i1 @offset_single_cmp() {
140 ; CHECK-LABEL: @offset_single_cmp(
141 ; CHECK-NEXT:    ret i1 false
143   %m = alloca i8, i32 4
144   %n = alloca i8, i32 4
145   %rhs = getelementptr i8, ptr %n, i32 4
146   %cmp = icmp eq ptr %m, %rhs
147   ret i1 %cmp
150 declare void @witness(i1, i1)
152 define void @consistent_fold1() {
153 ; CHECK-LABEL: @consistent_fold1(
154 ; CHECK-NEXT:    [[RHS2:%.*]] = call ptr @hidden_inttoptr()
155 ; CHECK-NEXT:    call void @witness(i1 false, i1 false)
156 ; CHECK-NEXT:    ret void
158   %m = alloca i8, i32 4
159   %rhs = inttoptr i64 2048 to ptr
160   %rhs2 = call ptr @hidden_inttoptr()
161   %cmp1 = icmp eq ptr %m, %rhs
162   %cmp2 = icmp eq ptr %m, %rhs2
163   call void @witness(i1 %cmp1, i1 %cmp2)
164   ret void
167 define void @consistent_fold2() {
168 ; CHECK-LABEL: @consistent_fold2(
169 ; CHECK-NEXT:    [[N2:%.*]] = alloca [4 x i8], align 1
170 ; CHECK-NEXT:    [[RHS2:%.*]] = call ptr @hidden_offset(ptr nonnull [[N2]])
171 ; CHECK-NEXT:    call void @witness(i1 false, i1 false)
172 ; CHECK-NEXT:    ret void
174   %m = alloca i8, i32 4
175   %n = alloca i8, i32 4
176   %rhs = getelementptr i8, ptr %n, i32 4
177   %rhs2 = call ptr @hidden_offset(ptr %n)
178   %cmp1 = icmp eq ptr %m, %rhs
179   %cmp2 = icmp eq ptr %m, %rhs2
180   call void @witness(i1 %cmp1, i1 %cmp2)
181   ret void
184 define void @consistent_fold3() {
185 ; CHECK-LABEL: @consistent_fold3(
186 ; CHECK-NEXT:    [[RHS2:%.*]] = call ptr @hidden_inttoptr()
187 ; CHECK-NEXT:    call void @witness(i1 false, i1 false)
188 ; CHECK-NEXT:    ret void
190   %m = alloca i8, i32 4
191   %lgp = load ptr, ptr @gp, align 8
192   %rhs2 = call ptr @hidden_inttoptr()
193   %cmp1 = icmp eq ptr %m, %lgp
194   %cmp2 = icmp eq ptr %m, %rhs2
195   call void @witness(i1 %cmp1, i1 %cmp2)
196   ret void
199 define void @neg_consistent_fold4() {
200 ; CHECK-LABEL: @neg_consistent_fold4(
201 ; CHECK-NEXT:    call void @witness(i1 false, i1 false)
202 ; CHECK-NEXT:    ret void
204   %m = alloca i8, i32 4
205   %lgp = load ptr, ptr @gp, align 8
206   %cmp1 = icmp eq ptr %m, %lgp
207   %cmp2 = icmp eq ptr %m, %lgp
208   call void @witness(i1 %cmp1, i1 %cmp2)
209   ret void
212 ; A nocapture call can't cause a consistent result issue as it is (by
213 ; assumption) not able to contain a comparison which might capture the
214 ; address.
216 declare void @unknown(ptr)
218 define i1 @consistent_nocapture_inttoptr() {
219 ; CHECK-LABEL: @consistent_nocapture_inttoptr(
220 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
221 ; CHECK-NEXT:    call void @unknown(ptr nocapture nonnull [[M1]])
222 ; CHECK-NEXT:    ret i1 false
224   %m = alloca i8, i32 4
225   call void @unknown(ptr nocapture %m)
226   %rhs = inttoptr i64 2048 to ptr
227   %cmp = icmp eq ptr %m, %rhs
228   ret i1 %cmp
231 define i1 @consistent_nocapture_offset() {
232 ; CHECK-LABEL: @consistent_nocapture_offset(
233 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
234 ; CHECK-NEXT:    call void @unknown(ptr nocapture nonnull [[M1]])
235 ; CHECK-NEXT:    ret i1 false
237   %m = alloca i8, i32 4
238   call void @unknown(ptr nocapture %m)
239   %n = alloca i8, i32 4
240   %rhs = getelementptr i8, ptr %n, i32 4
241   %cmp = icmp eq ptr %m, %rhs
242   ret i1 %cmp
245 @gp = global ptr null, align 8
247 define i1 @consistent_nocapture_through_global() {
248 ; CHECK-LABEL: @consistent_nocapture_through_global(
249 ; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1
250 ; CHECK-NEXT:    call void @unknown(ptr nocapture nonnull [[M1]])
251 ; CHECK-NEXT:    ret i1 false
253   %m = alloca i8, i32 4
254   call void @unknown(ptr nocapture %m)
255   %lgp = load ptr, ptr @gp, align 8, !nonnull !{}
256   %cmp = icmp eq ptr %m, %lgp
257   ret i1 %cmp
260 define void @select_alloca_unrelated_ptr(i1 %c, ptr %p, ptr %p2) {
261 ; CHECK-LABEL: @select_alloca_unrelated_ptr(
262 ; CHECK-NEXT:    [[M:%.*]] = alloca i8, align 1
263 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[M]], [[P:%.*]]
264 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[C:%.*]], ptr [[M]], ptr [[P2:%.*]]
265 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[S]], [[P]]
266 ; CHECK-NEXT:    call void @witness(i1 [[CMP1]], i1 [[CMP2]])
267 ; CHECK-NEXT:    ret void
269   %m = alloca i8
270   %cmp1 = icmp eq ptr %m, %p
271   %s = select i1 %c, ptr %m, ptr %p2
272   %cmp2 = icmp eq ptr %s, %p
273   call void @witness(i1 %cmp1, i1 %cmp2)
274   ret void
277 define void @alloca_offset_icmp(ptr %p, i32 %offset) {
278 ; CHECK-LABEL: @alloca_offset_icmp(
279 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[OFFSET:%.*]], 0
280 ; CHECK-NEXT:    call void @witness(i1 false, i1 [[CMP2]])
281 ; CHECK-NEXT:    ret void
283   %m = alloca [4 x i8]
284   %g = getelementptr i8, ptr %m, i32 %offset
285   %cmp1 = icmp eq ptr %m, %p
286   %cmp2 = icmp eq ptr %m, %g
287   call void @witness(i1 %cmp1, i1 %cmp2)
288   ret void