xref: /llvm-project/llvm/test/Transforms/InstCombine/deref-alloc-fns.ll (revision 195362929cd79c0202f73bcbab9a09b8a1a3beaa)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare noalias ptr @malloc(i64) allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc"
5declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc"
6declare noalias ptr @realloc(ptr nocapture, i64) allockind("realloc") allocsize(1) "alloc-family"="malloc"
7declare noalias nonnull ptr @_Znam(i64) ; throwing version of 'new'
8declare noalias nonnull ptr @_Znwm(i64) ; throwing version of 'new'
9declare noalias ptr @strdup(ptr)
10declare noalias ptr @aligned_alloc(i64 allocalign, i64) allockind("alloc,uninitialized,aligned") allocsize(1) "alloc-family"="malloc"
11declare noalias align 16 ptr @memalign(i64 allocalign, i64) allocsize(1)
12; new[](unsigned int, align_val_t)
13declare noalias ptr @_ZnamSt11align_val_t(i64 %size, i64 %align)
14
15declare ptr @my_malloc(i64) allocsize(0)
16declare ptr @my_calloc(i64, i64) allocsize(0, 1)
17
18@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1
19
20define noalias ptr @malloc_nonconstant_size(i64 %n) {
21; CHECK-LABEL: @malloc_nonconstant_size(
22; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @malloc(i64 [[N:%.*]])
23; CHECK-NEXT:    ret ptr [[CALL]]
24;
25  %call = tail call noalias ptr @malloc(i64 %n)
26  ret ptr %call
27}
28
29define noalias ptr @malloc_constant_size() {
30; CHECK-LABEL: @malloc_constant_size(
31; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(40) ptr @malloc(i64 40)
32; CHECK-NEXT:    ret ptr [[CALL]]
33;
34  %call = tail call noalias ptr @malloc(i64 40)
35  ret ptr %call
36}
37
38define noalias ptr @aligned_alloc_constant_size() {
39; CHECK-LABEL: @aligned_alloc_constant_size(
40; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias align 32 dereferenceable_or_null(512) ptr @aligned_alloc(i64 32, i64 512)
41; CHECK-NEXT:    ret ptr [[CALL]]
42;
43  %call = tail call noalias ptr @aligned_alloc(i64 32, i64 512)
44  ret ptr %call
45}
46
47define noalias ptr @aligned_alloc_unknown_size_nonzero(i1 %c) {
48; CHECK-LABEL: @aligned_alloc_unknown_size_nonzero(
49; CHECK-NEXT:    [[SIZE:%.*]] = select i1 [[C:%.*]], i64 64, i64 128
50; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias align 32 ptr @aligned_alloc(i64 32, i64 [[SIZE]])
51; CHECK-NEXT:    ret ptr [[CALL]]
52;
53  %size = select i1 %c, i64 64, i64 128
54  %call = tail call noalias ptr @aligned_alloc(i64 32, i64 %size)
55  ret ptr %call
56}
57
58define noalias ptr @aligned_alloc_unknown_size_possibly_zero(i1 %c) {
59; CHECK-LABEL: @aligned_alloc_unknown_size_possibly_zero(
60; CHECK-NEXT:    [[SIZE:%.*]] = select i1 [[C:%.*]], i64 64, i64 0
61; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias align 32 ptr @aligned_alloc(i64 32, i64 [[SIZE]])
62; CHECK-NEXT:    ret ptr [[CALL]]
63;
64  %size = select i1 %c, i64 64, i64 0
65  %call = tail call noalias ptr @aligned_alloc(i64 32, i64 %size)
66  ret ptr %call
67}
68
69define noalias ptr @aligned_alloc_unknown_align(i64 %align) {
70; CHECK-LABEL: @aligned_alloc_unknown_align(
71; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(128) ptr @aligned_alloc(i64 [[ALIGN:%.*]], i64 128)
72; CHECK-NEXT:    ret ptr [[CALL]]
73;
74  %call = tail call noalias ptr @aligned_alloc(i64 %align, i64 128)
75  ret ptr %call
76}
77
78declare noalias ptr @foo(ptr, ptr, ptr)
79
80define noalias ptr @aligned_alloc_dynamic_args(i64 %align, i64 %size) {
81; CHECK-LABEL: @aligned_alloc_dynamic_args(
82; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(1024) ptr @aligned_alloc(i64 [[ALIGN:%.*]], i64 1024)
83; CHECK-NEXT:    [[CALL_1:%.*]] = tail call noalias dereferenceable_or_null(1024) ptr @aligned_alloc(i64 0, i64 1024)
84; CHECK-NEXT:    [[CALL_2:%.*]] = tail call noalias align 32 ptr @aligned_alloc(i64 32, i64 [[SIZE:%.*]])
85; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @foo(ptr [[CALL]], ptr [[CALL_1]], ptr [[CALL_2]])
86; CHECK-NEXT:    ret ptr [[CALL]]
87;
88  %call = tail call noalias ptr @aligned_alloc(i64 %align, i64 1024)
89  %call_1 = tail call noalias ptr @aligned_alloc(i64 0, i64 1024)
90  %call_2 = tail call noalias ptr @aligned_alloc(i64 32, i64 %size)
91
92  call ptr @foo(ptr %call, ptr %call_1, ptr %call_2)
93  ret ptr %call
94}
95
96define noalias ptr @memalign_constant_size() {
97; CHECK-LABEL: @memalign_constant_size(
98; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias align 32 dereferenceable_or_null(512) ptr @memalign(i64 32, i64 512)
99; CHECK-NEXT:    ret ptr [[CALL]]
100;
101  %call = tail call noalias ptr @memalign(i64 32, i64 512)
102  ret ptr %call
103}
104
105define noalias ptr @memalign_unknown_size_nonzero(i1 %c) {
106; CHECK-LABEL: @memalign_unknown_size_nonzero(
107; CHECK-NEXT:    [[SIZE:%.*]] = select i1 [[C:%.*]], i64 64, i64 128
108; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias align 32 ptr @memalign(i64 32, i64 [[SIZE]])
109; CHECK-NEXT:    ret ptr [[CALL]]
110;
111  %size = select i1 %c, i64 64, i64 128
112  %call = tail call noalias ptr @memalign(i64 32, i64 %size)
113  ret ptr %call
114}
115
116define noalias ptr @memalign_unknown_size_possibly_zero(i1 %c) {
117; CHECK-LABEL: @memalign_unknown_size_possibly_zero(
118; CHECK-NEXT:    [[SIZE:%.*]] = select i1 [[C:%.*]], i64 64, i64 0
119; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias align 32 ptr @memalign(i64 32, i64 [[SIZE]])
120; CHECK-NEXT:    ret ptr [[CALL]]
121;
122  %size = select i1 %c, i64 64, i64 0
123  %call = tail call noalias ptr @memalign(i64 32, i64 %size)
124  ret ptr %call
125}
126
127define noalias ptr @memalign_unknown_align(i64 %align) {
128; CHECK-LABEL: @memalign_unknown_align(
129; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(128) ptr @memalign(i64 [[ALIGN:%.*]], i64 128)
130; CHECK-NEXT:    ret ptr [[CALL]]
131;
132  %call = tail call noalias ptr @memalign(i64 %align, i64 128)
133  ret ptr %call
134}
135
136define noalias ptr @malloc_constant_size2() {
137; CHECK-LABEL: @malloc_constant_size2(
138; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(40) ptr @malloc(i64 40)
139; CHECK-NEXT:    ret ptr [[CALL]]
140;
141  %call = tail call noalias dereferenceable_or_null(80) ptr @malloc(i64 40)
142  ret ptr %call
143}
144
145define noalias ptr @malloc_constant_size3() {
146; CHECK-LABEL: @malloc_constant_size3(
147; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable(80) dereferenceable_or_null(40) ptr @malloc(i64 40)
148; CHECK-NEXT:    ret ptr [[CALL]]
149;
150  %call = tail call noalias dereferenceable(80) ptr @malloc(i64 40)
151  ret ptr %call
152}
153
154define noalias ptr @malloc_constant_zero_size() {
155; CHECK-LABEL: @malloc_constant_zero_size(
156; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @malloc(i64 0)
157; CHECK-NEXT:    ret ptr [[CALL]]
158;
159  %call = tail call noalias ptr @malloc(i64 0)
160  ret ptr %call
161}
162
163define noalias ptr @realloc_nonconstant_size(ptr %p, i64 %n) {
164; CHECK-LABEL: @realloc_nonconstant_size(
165; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @realloc(ptr [[P:%.*]], i64 [[N:%.*]])
166; CHECK-NEXT:    ret ptr [[CALL]]
167;
168  %call = tail call noalias ptr @realloc(ptr %p, i64 %n)
169  ret ptr %call
170}
171
172define noalias ptr @realloc_constant_zero_size(ptr %p) {
173; CHECK-LABEL: @realloc_constant_zero_size(
174; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @realloc(ptr [[P:%.*]], i64 0)
175; CHECK-NEXT:    ret ptr [[CALL]]
176;
177  %call = tail call noalias ptr @realloc(ptr %p, i64 0)
178  ret ptr %call
179}
180
181define noalias ptr @realloc_constant_size(ptr %p) {
182; CHECK-LABEL: @realloc_constant_size(
183; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(40) ptr @realloc(ptr [[P:%.*]], i64 40)
184; CHECK-NEXT:    ret ptr [[CALL]]
185;
186  %call = tail call noalias ptr @realloc(ptr %p, i64 40)
187  ret ptr %call
188}
189
190define noalias ptr @calloc_nonconstant_size(i64 %n) {
191; CHECK-LABEL: @calloc_nonconstant_size(
192; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 1, i64 [[N:%.*]])
193; CHECK-NEXT:    ret ptr [[CALL]]
194;
195  %call = tail call noalias ptr @calloc(i64 1, i64 %n)
196  ret ptr %call
197}
198
199define noalias ptr @calloc_nonconstant_size2(i64 %n) {
200; CHECK-LABEL: @calloc_nonconstant_size2(
201; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 [[N:%.*]], i64 0)
202; CHECK-NEXT:    ret ptr [[CALL]]
203;
204  %call = tail call noalias ptr @calloc(i64 %n, i64 0)
205  ret ptr %call
206}
207
208define noalias ptr @calloc_nonconstant_size3(i64 %n) {
209; CHECK-LABEL: @calloc_nonconstant_size3(
210; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 [[N:%.*]], i64 [[N]])
211; CHECK-NEXT:    ret ptr [[CALL]]
212;
213  %call = tail call noalias ptr @calloc(i64 %n, i64 %n)
214  ret ptr %call
215}
216
217define noalias ptr @calloc_constant_zero_size() {
218; CHECK-LABEL: @calloc_constant_zero_size(
219; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 0, i64 0)
220; CHECK-NEXT:    ret ptr [[CALL]]
221;
222  %call = tail call noalias ptr @calloc(i64 0, i64 0)
223  ret ptr %call
224}
225
226define noalias ptr @calloc_constant_zero_size2(i64 %n) {
227; CHECK-LABEL: @calloc_constant_zero_size2(
228; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 [[N:%.*]], i64 0)
229; CHECK-NEXT:    ret ptr [[CALL]]
230;
231  %call = tail call noalias ptr @calloc(i64 %n, i64 0)
232  ret ptr %call
233}
234
235
236define noalias ptr @calloc_constant_zero_size3(i64 %n) {
237; CHECK-LABEL: @calloc_constant_zero_size3(
238; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 0, i64 [[N:%.*]])
239; CHECK-NEXT:    ret ptr [[CALL]]
240;
241  %call = tail call noalias ptr @calloc(i64 0, i64 %n)
242  ret ptr %call
243}
244
245define noalias ptr @calloc_constant_zero_size4(i64 %n) {
246; CHECK-LABEL: @calloc_constant_zero_size4(
247; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 0, i64 1)
248; CHECK-NEXT:    ret ptr [[CALL]]
249;
250  %call = tail call noalias ptr @calloc(i64 0, i64 1)
251  ret ptr %call
252}
253
254define noalias ptr @calloc_constant_zero_size5(i64 %n) {
255; CHECK-LABEL: @calloc_constant_zero_size5(
256; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 1, i64 0)
257; CHECK-NEXT:    ret ptr [[CALL]]
258;
259  %call = tail call noalias ptr @calloc(i64 1, i64 0)
260  ret ptr %call
261}
262
263define noalias ptr @calloc_constant_size() {
264; CHECK-LABEL: @calloc_constant_size(
265; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(128) ptr @calloc(i64 16, i64 8)
266; CHECK-NEXT:    ret ptr [[CALL]]
267;
268  %call = tail call noalias ptr @calloc(i64 16, i64 8)
269  ret ptr %call
270}
271
272define noalias ptr @calloc_constant_size_overflow() {
273; CHECK-LABEL: @calloc_constant_size_overflow(
274; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @calloc(i64 2000000000000, i64 80000000000)
275; CHECK-NEXT:    ret ptr [[CALL]]
276;
277  %call = tail call noalias ptr @calloc(i64 2000000000000, i64 80000000000)
278  ret ptr %call
279}
280
281define noalias ptr @op_new_nonconstant_size(i64 %n) {
282; CHECK-LABEL: @op_new_nonconstant_size(
283; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr @_Znam(i64 [[N:%.*]])
284; CHECK-NEXT:    ret ptr [[CALL]]
285;
286  %call = tail call ptr @_Znam(i64 %n)
287  ret ptr %call
288}
289
290define noalias ptr @op_new_constant_size() {
291; CHECK-LABEL: @op_new_constant_size(
292; CHECK-NEXT:    [[CALL:%.*]] = tail call dereferenceable(40) ptr @_Znam(i64 40)
293; CHECK-NEXT:    ret ptr [[CALL]]
294;
295  %call = tail call ptr @_Znam(i64 40)
296  ret ptr %call
297}
298
299define noalias ptr @op_new_constant_size2() {
300; CHECK-LABEL: @op_new_constant_size2(
301; CHECK-NEXT:    [[CALL:%.*]] = tail call dereferenceable(40) ptr @_Znwm(i64 40)
302; CHECK-NEXT:    ret ptr [[CALL]]
303;
304  %call = tail call ptr @_Znwm(i64 40)
305  ret ptr %call
306}
307
308define noalias ptr @op_new_constant_zero_size() {
309; CHECK-LABEL: @op_new_constant_zero_size(
310; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr @_Znam(i64 0)
311; CHECK-NEXT:    ret ptr [[CALL]]
312;
313  %call = tail call ptr @_Znam(i64 0)
314  ret ptr %call
315}
316
317define noalias ptr @strdup_constant_str() {
318; CHECK-LABEL: @strdup_constant_str(
319; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(6) ptr @strdup(ptr nonnull @.str)
320; CHECK-NEXT:    ret ptr [[CALL]]
321;
322  %call = tail call noalias ptr @strdup(ptr @.str)
323  ret ptr %call
324}
325
326define noalias ptr @strdup_notconstant_str(ptr %str) {
327; CHECK-LABEL: @strdup_notconstant_str(
328; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @strdup(ptr [[STR:%.*]])
329; CHECK-NEXT:    ret ptr [[CALL]]
330;
331  %call = tail call noalias ptr @strdup(ptr %str)
332  ret ptr %call
333}
334
335; OSS-Fuzz #23214
336; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23214
337define noalias ptr @ossfuzz_23214() {
338; CHECK-LABEL: @ossfuzz_23214(
339; CHECK-NEXT:  bb:
340; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias dereferenceable_or_null(512) ptr @aligned_alloc(i64 -9223372036854775808, i64 512)
341; CHECK-NEXT:    ret ptr [[CALL]]
342;
343bb:
344  %and = and i64 -1, -9223372036854775808
345  %call = tail call noalias ptr @aligned_alloc(i64 %and, i64 512)
346  ret ptr %call
347}
348
349define noalias ptr @op_new_align() {
350; CHECK-LABEL: @op_new_align(
351; CHECK-NEXT:    [[CALL:%.*]] = tail call align 32 dereferenceable_or_null(32) ptr @_ZnamSt11align_val_t(i64 32, i64 32)
352; CHECK-NEXT:    ret ptr [[CALL]]
353;
354  %call = tail call ptr @_ZnamSt11align_val_t(i64 32, i64 32)
355  ret ptr %call
356}
357
358define ptr @my_malloc_constant_size() {
359; CHECK-LABEL: @my_malloc_constant_size(
360; CHECK-NEXT:    [[CALL:%.*]] = call dereferenceable_or_null(32) ptr @my_malloc(i64 32)
361; CHECK-NEXT:    ret ptr [[CALL]]
362;
363  %call = call ptr @my_malloc(i64 32)
364  ret ptr %call
365}
366
367define ptr @my_calloc_constant_size() {
368; CHECK-LABEL: @my_calloc_constant_size(
369; CHECK-NEXT:    [[CALL:%.*]] = call dereferenceable_or_null(128) ptr @my_calloc(i64 32, i64 4)
370; CHECK-NEXT:    ret ptr [[CALL]]
371;
372  %call = call ptr @my_calloc(i64 32, i64 4)
373  ret ptr %call
374}
375
376define ptr @virtual_constant_size(ptr %alloc) {
377; CHECK-LABEL: @virtual_constant_size(
378; CHECK-NEXT:    [[CALL:%.*]] = call dereferenceable_or_null(16) ptr [[ALLOC:%.*]](i64 16) #[[ATTR5:[0-9]+]]
379; CHECK-NEXT:    ret ptr [[CALL]]
380;
381  %call = call ptr %alloc(i64 16) allocsize(0)
382  ret ptr %call
383}
384