[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Attributor / nofree.ll
blobbeb3a24723b734f616679ca5264bd72046f9d7ea
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4 ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
7 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
9 ; Test cases specifically designed for the "nofree" function attribute.
10 ; We use FIXME's to indicate problems and missing attributes.
12 ; Free functions
13 declare void @free(i8* nocapture) local_unnamed_addr #1
14 declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #0
15 declare void @_ZdaPv(i8*) local_unnamed_addr #2
18 ; TEST 1 (positive case)
19 define void @only_return() #0 {
20 ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
21 ; IS__TUNIT____-LABEL: define {{[^@]+}}@only_return
22 ; IS__TUNIT____-SAME: () #[[ATTR3:[0-9]+]] {
23 ; IS__TUNIT____-NEXT:    ret void
25 ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
26 ; IS__CGSCC____-LABEL: define {{[^@]+}}@only_return
27 ; IS__CGSCC____-SAME: () #[[ATTR3:[0-9]+]] {
28 ; IS__CGSCC____-NEXT:    ret void
30   ret void
34 ; TEST 2 (negative case)
35 ; Only free
36 ; void only_free(char* p) {
37 ;    free(p);
38 ; }
40 define void @only_free(i8* nocapture %0) local_unnamed_addr #0 {
41 ; CHECK: Function Attrs: noinline nounwind uwtable
42 ; CHECK-LABEL: define {{[^@]+}}@only_free
43 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
44 ; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP0]]) #[[ATTR0:[0-9]+]]
45 ; CHECK-NEXT:    ret void
47   tail call void @free(i8* %0) #1
48   ret void
52 ; TEST 3 (negative case)
53 ; Free occurs in same scc.
54 ; void free_in_scc1(char*p){
55 ;    free_in_scc2(p);
56 ; }
57 ; void free_in_scc2(char*p){
58 ;    free_in_scc1(p);
59 ;    free(p);
60 ; }
63 define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 {
64 ; CHECK: Function Attrs: noinline nounwind uwtable
65 ; CHECK-LABEL: define {{[^@]+}}@free_in_scc1
66 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
67 ; CHECK-NEXT:    tail call void @free_in_scc2(i8* nocapture [[TMP0]]) #[[ATTR0]]
68 ; CHECK-NEXT:    ret void
70   tail call void @free_in_scc2(i8* %0) #1
71   ret void
75 define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr #0 {
76 ; CHECK: Function Attrs: noinline nounwind uwtable
77 ; CHECK-LABEL: define {{[^@]+}}@free_in_scc2
78 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
79 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[TMP0]], null
80 ; CHECK-NEXT:    br i1 [[CMP]], label [[REC:%.*]], label [[CALL:%.*]]
81 ; CHECK:       call:
82 ; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP0]]) #[[ATTR0]]
83 ; CHECK-NEXT:    br label [[END:%.*]]
84 ; CHECK:       rec:
85 ; CHECK-NEXT:    tail call void @free_in_scc1(i8* nocapture [[TMP0]]) #[[ATTR0]]
86 ; CHECK-NEXT:    br label [[END]]
87 ; CHECK:       end:
88 ; CHECK-NEXT:    ret void
90   %cmp = icmp eq i8* %0, null
91   br i1 %cmp, label %rec, label %call
92 call:
93   tail call void @free(i8* %0) #1
94   br label %end
95 rec:
96   tail call void @free_in_scc1(i8* %0)
97   br label %end
98 end:
99   ret void
103 ; TEST 4 (positive case)
104 ; Free doesn't occur.
105 ; void mutual_recursion1(){
106 ;    mutual_recursion2();
107 ; }
108 ; void mutual_recursion2(){
109 ;     mutual_recursion1();
110 ; }
113 define void @mutual_recursion1() #0 {
114 ; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn
115 ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion1
116 ; NOT_CGSCC_NPM-SAME: () #[[ATTR4:[0-9]+]] {
117 ; NOT_CGSCC_NPM-NEXT:    unreachable
119 ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn
120 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion1
121 ; IS__CGSCC_NPM-SAME: () #[[ATTR4:[0-9]+]] {
122 ; IS__CGSCC_NPM-NEXT:    unreachable
124   call void @mutual_recursion2()
125   ret void
128 define void @mutual_recursion2() #0 {
129 ; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn
130 ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion2
131 ; NOT_CGSCC_NPM-SAME: () #[[ATTR4]] {
132 ; NOT_CGSCC_NPM-NEXT:    unreachable
134 ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn
135 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion2
136 ; IS__CGSCC_NPM-SAME: () #[[ATTR4]] {
137 ; IS__CGSCC_NPM-NEXT:    unreachable
139   call void @mutual_recursion1()
140   ret void
144 ; TEST 5
145 ; C++ delete operation (negative case)
146 ; void delete_op (char p[]){
147 ;     delete [] p;
148 ; }
150 define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 {
151 ; CHECK: Function Attrs: noinline nounwind uwtable
152 ; CHECK-LABEL: define {{[^@]+}}@_Z9delete_opPc
153 ; CHECK-SAME: (i8* [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
154 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
155 ; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
156 ; CHECK:       3:
157 ; CHECK-NEXT:    tail call void @_ZdaPv(i8* nonnull [[TMP0]]) #[[ATTR2:[0-9]+]]
158 ; CHECK-NEXT:    br label [[TMP4]]
159 ; CHECK:       4:
160 ; CHECK-NEXT:    ret void
162   %2 = icmp eq i8* %0, null
163   br i1 %2, label %4, label %3
165 ; <label>:3:                                      ; preds = %1
166   tail call void @_ZdaPv(i8* nonnull %0) #2
167   br label %4
169 ; <label>:4:                                      ; preds = %3, %1
170   ret void
174 ; TEST 6 (negative case)
175 ; Call realloc
176 define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0 {
177 ; CHECK: Function Attrs: noinline nounwind uwtable
178 ; CHECK-LABEL: define {{[^@]+}}@call_realloc
179 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]], i64 [[TMP1:%.*]]) local_unnamed_addr #[[ATTR1]] {
180 ; CHECK-NEXT:    [[RET:%.*]] = tail call i8* @realloc(i8* nocapture [[TMP0]], i64 [[TMP1]]) #[[ATTR2]]
181 ; CHECK-NEXT:    ret i8* [[RET]]
183   %ret = tail call i8* @realloc(i8* %0, i64 %1) #2
184   ret i8* %ret
188 ; TEST 7 (positive case)
189 ; Call function declaration with "nofree"
192 ; CHECK: Function Attrs:  nofree noinline nounwind readnone uwtable
193 ; CHECK-NEXT: declare void @nofree_function()
194 declare void @nofree_function() nofree readnone #0
196 define void @call_nofree_function() #0 {
197 ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
198 ; IS__TUNIT____-LABEL: define {{[^@]+}}@call_nofree_function
199 ; IS__TUNIT____-SAME: () #[[ATTR3]] {
200 ; IS__TUNIT____-NEXT:    ret void
202 ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
203 ; IS__CGSCC____-LABEL: define {{[^@]+}}@call_nofree_function
204 ; IS__CGSCC____-SAME: () #[[ATTR3]] {
205 ; IS__CGSCC____-NEXT:    ret void
207   tail call void @nofree_function()
208   ret void
211 ; TEST 8 (negative case)
212 ; Call function declaration without "nofree"
215 ; CHECK: Function Attrs: noinline nounwind uwtable
216 ; CHECK-NEXT: declare void @maybe_free()
217 declare void @maybe_free() #0
220 define void @call_maybe_free() #0 {
221 ; CHECK: Function Attrs: noinline nounwind uwtable
222 ; CHECK-LABEL: define {{[^@]+}}@call_maybe_free
223 ; CHECK-SAME: () #[[ATTR1]] {
224 ; CHECK-NEXT:    tail call void @maybe_free() #[[ATTR0]]
225 ; CHECK-NEXT:    ret void
227   tail call void @maybe_free()
228   ret void
232 ; TEST 9 (negative case)
233 ; Call both of above functions
235 define void @call_both() #0 {
236 ; CHECK: Function Attrs: noinline nounwind uwtable
237 ; CHECK-LABEL: define {{[^@]+}}@call_both
238 ; CHECK-SAME: () #[[ATTR1]] {
239 ; CHECK-NEXT:    tail call void @maybe_free() #[[ATTR0]]
240 ; CHECK-NEXT:    ret void
242   tail call void @maybe_free()
243   tail call void @nofree_function()
244   ret void
248 ; TEST 10 (positive case)
249 ; Call intrinsic function
250 ; CHECK: Function Attrs: nofree nosync nounwind readnone speculatable willreturn
251 ; CHECK-NEXT: declare float @llvm.floor.f32(float)
252 declare float @llvm.floor.f32(float)
254 define void @call_floor(float %a) #0 {
255 ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
256 ; IS__TUNIT____-LABEL: define {{[^@]+}}@call_floor
257 ; IS__TUNIT____-SAME: (float [[A:%.*]]) #[[ATTR3]] {
258 ; IS__TUNIT____-NEXT:    ret void
260 ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
261 ; IS__CGSCC____-LABEL: define {{[^@]+}}@call_floor
262 ; IS__CGSCC____-SAME: (float [[A:%.*]]) #[[ATTR3]] {
263 ; IS__CGSCC____-NEXT:    ret void
265   tail call float @llvm.floor.f32(float %a)
266   ret void
269 define float @call_floor2(float %a) #0 {
270 ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
271 ; IS__TUNIT____-LABEL: define {{[^@]+}}@call_floor2
272 ; IS__TUNIT____-SAME: (float [[A:%.*]]) #[[ATTR3]] {
273 ; IS__TUNIT____-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR11:[0-9]+]]
274 ; IS__TUNIT____-NEXT:    ret float [[C]]
276 ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
277 ; IS__CGSCC____-LABEL: define {{[^@]+}}@call_floor2
278 ; IS__CGSCC____-SAME: (float [[A:%.*]]) #[[ATTR7:[0-9]+]] {
279 ; IS__CGSCC____-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR12:[0-9]+]]
280 ; IS__CGSCC____-NEXT:    ret float [[C]]
282   %c = tail call float @llvm.floor.f32(float %a)
283   ret float %c
286 ; TEST 11 (positive case)
287 ; Check propagation.
289 define void @f1() #0 {
290 ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
291 ; IS__TUNIT____-LABEL: define {{[^@]+}}@f1
292 ; IS__TUNIT____-SAME: () #[[ATTR3]] {
293 ; IS__TUNIT____-NEXT:    ret void
295 ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
296 ; IS__CGSCC____-LABEL: define {{[^@]+}}@f1
297 ; IS__CGSCC____-SAME: () #[[ATTR3]] {
298 ; IS__CGSCC____-NEXT:    ret void
300   tail call void @nofree_function()
301   ret void
304 define void @f2() #0 {
305 ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
306 ; IS__TUNIT____-LABEL: define {{[^@]+}}@f2
307 ; IS__TUNIT____-SAME: () #[[ATTR3]] {
308 ; IS__TUNIT____-NEXT:    ret void
310 ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
311 ; IS__CGSCC____-LABEL: define {{[^@]+}}@f2
312 ; IS__CGSCC____-SAME: () #[[ATTR3]] {
313 ; IS__CGSCC____-NEXT:    ret void
315   tail call void @f1()
316   ret void
319 ; TEST 12 NoFree argument - positive.
320 define double @test12(double* nocapture readonly %a) {
321 ; IS__TUNIT____: Function Attrs: nofree nounwind
322 ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12
323 ; IS__TUNIT____-SAME: (double* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR7:[0-9]+]] {
324 ; IS__TUNIT____-NEXT:  entry:
325 ; IS__TUNIT____-NEXT:    [[TMP0:%.*]] = load double, double* [[A]], align 8
326 ; IS__TUNIT____-NEXT:    [[CALL:%.*]] = tail call double @cos(double [[TMP0]]) #[[ATTR2]]
327 ; IS__TUNIT____-NEXT:    ret double [[CALL]]
329 ; IS__CGSCC____: Function Attrs: nofree nounwind
330 ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12
331 ; IS__CGSCC____-SAME: (double* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR8:[0-9]+]] {
332 ; IS__CGSCC____-NEXT:  entry:
333 ; IS__CGSCC____-NEXT:    [[TMP0:%.*]] = load double, double* [[A]], align 8
334 ; IS__CGSCC____-NEXT:    [[CALL:%.*]] = tail call double @cos(double [[TMP0]]) #[[ATTR2]]
335 ; IS__CGSCC____-NEXT:    ret double [[CALL]]
337 entry:
338   %0 = load double, double* %a, align 8
339   %call = tail call double @cos(double %0) #2
340   ret double %call
343 declare double @cos(double) nobuiltin nounwind nofree
345 ; FIXME: %a should be nofree.
346 ; TEST 13 NoFree argument - positive.
347 define noalias i32* @test13(i64* nocapture readonly %a) {
348 ; CHECK: Function Attrs: nounwind
349 ; CHECK-LABEL: define {{[^@]+}}@test13
350 ; CHECK-SAME: (i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR0]] {
351 ; CHECK-NEXT:  entry:
352 ; CHECK-NEXT:    [[TMP0:%.*]] = load i64, i64* [[A]], align 8
353 ; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias i8* @malloc(i64 [[TMP0]]) #[[ATTR2]]
354 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i8* [[CALL]] to i32*
355 ; CHECK-NEXT:    ret i32* [[TMP1]]
357 entry:
358   %0 = load i64, i64* %a, align 8
359   %call = tail call noalias i8* @malloc(i64 %0) #2
360   %1 = bitcast i8* %call to i32*
361   ret i32* %1
364 define void @test14(i8* nocapture %0, i8* nocapture %1) {
365 ; CHECK: Function Attrs: nounwind
366 ; CHECK-LABEL: define {{[^@]+}}@test14
367 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]], i8* nocapture nofree readnone [[TMP1:%.*]]) #[[ATTR0]] {
368 ; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP0]]) #[[ATTR0]]
369 ; CHECK-NEXT:    ret void
371   tail call void @free(i8* %0) #1
372   ret void
375 ; UTC_ARGS: --enable
377 define void @nonnull_assume_pos(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) {
378 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_pos
379 ; ATTRIBUTOR-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]])
380 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) #11 [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
381 ; ATTRIBUTOR-NEXT:    call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]])
382 ; ATTRIBUTOR-NEXT:    ret void
384 ; IS__TUNIT____-LABEL: define {{[^@]+}}@nonnull_assume_pos
385 ; IS__TUNIT____-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) {
386 ; IS__TUNIT____-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR12:[0-9]+]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
387 ; IS__TUNIT____-NEXT:    call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]])
388 ; IS__TUNIT____-NEXT:    ret void
390 ; IS__CGSCC____-LABEL: define {{[^@]+}}@nonnull_assume_pos
391 ; IS__CGSCC____-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) {
392 ; IS__CGSCC____-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR13:[0-9]+]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
393 ; IS__CGSCC____-NEXT:    call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]])
394 ; IS__CGSCC____-NEXT:    ret void
396   call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg3)]
397   call void @unknown(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4)
398   ret void
400 define void @nonnull_assume_neg(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) {
401 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_neg
402 ; ATTRIBUTOR-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]])
403 ; ATTRIBUTOR-NEXT:    call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]])
404 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
405 ; ATTRIBUTOR-NEXT:    ret void
407 ; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_neg
408 ; CHECK-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) {
409 ; CHECK-NEXT:    call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]])
410 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
411 ; CHECK-NEXT:    ret void
413   call void @unknown(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4)
414   call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg3)]
415   ret void
417 define void @nonnull_assume_call(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) {
418 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_call
419 ; ATTRIBUTOR-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]])
420 ; ATTRIBUTOR-NEXT:    call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]])
421 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(i8* noalias readnone [[ARG1]])
422 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(i8* noalias readnone [[ARG2]])
423 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
424 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(i8* noalias nofree readnone [[ARG3]])
425 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(i8* noalias readnone [[ARG4]])
426 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(i8* noalias nofree readnone [[ARG1]])
427 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(i8* noalias readnone [[ARG2]])
428 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG4]]) ]
429 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(i8* noalias nofree readnone [[ARG3]])
430 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(i8* noalias nofree readnone [[ARG4]])
431 ; ATTRIBUTOR-NEXT:    ret void
433 ; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_call
434 ; CHECK-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) {
435 ; CHECK-NEXT:    call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]])
436 ; CHECK-NEXT:    call void @use_i8_ptr(i8* noalias nocapture readnone [[ARG1]]) #[[ATTR0]]
437 ; CHECK-NEXT:    call void @use_i8_ptr(i8* noalias nocapture readnone [[ARG2]]) #[[ATTR0]]
438 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
439 ; CHECK-NEXT:    call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[ARG3]]) #[[ATTR0]]
440 ; CHECK-NEXT:    call void @use_i8_ptr(i8* noalias nocapture readnone [[ARG4]]) #[[ATTR0]]
441 ; CHECK-NEXT:    call void @use_i8_ptr_ret(i8* noalias nocapture nofree readnone [[ARG1]]) #[[ATTR0]]
442 ; CHECK-NEXT:    call void @use_i8_ptr_ret(i8* noalias nocapture readnone [[ARG2]]) #[[ATTR0]]
443 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG4]]) ]
444 ; CHECK-NEXT:    call void @use_i8_ptr_ret(i8* noalias nocapture nofree readnone [[ARG3]]) #[[ATTR0]]
445 ; CHECK-NEXT:    call void @use_i8_ptr_ret(i8* noalias nocapture nofree readnone [[ARG4]]) #[[ATTR0]]
446 ; CHECK-NEXT:    ret void
448   call void @unknown(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4)
449   call void @use_i8_ptr(i8* %arg1)
450   call void @use_i8_ptr(i8* %arg2)
451   call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg3)]
452   call void @use_i8_ptr(i8* %arg3)
453   call void @use_i8_ptr(i8* %arg4)
454   call void @use_i8_ptr_ret(i8* %arg1)
455   call void @use_i8_ptr_ret(i8* %arg2)
456   call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg4)]
457   call void @use_i8_ptr_ret(i8* %arg3)
458   call void @use_i8_ptr_ret(i8* %arg4)
459   ret void
461 declare void @llvm.assume(i1)
462 declare void @unknown(i8*, i8*, i8*, i8*)
463 declare void @use_i8_ptr(i8* nocapture readnone) nounwind
464 declare void @use_i8_ptr_ret(i8* nocapture readnone) nounwind willreturn
466 declare noalias i8* @malloc(i64)
468 attributes #0 = { nounwind uwtable noinline }
469 attributes #1 = { nounwind }
470 attributes #2 = { nobuiltin nounwind }
472 ; IS__TUNIT____: attributes #[[ATTR0]] = { nounwind }
473 ; IS__TUNIT____: attributes #[[ATTR1]] = { noinline nounwind uwtable }
474 ; IS__TUNIT____: attributes #[[ATTR2]] = { nobuiltin nounwind }
475 ; IS__TUNIT____: attributes #[[ATTR3]] = { nofree noinline nosync nounwind readnone uwtable willreturn }
476 ; IS__TUNIT____: attributes #[[ATTR4]] = { nofree noinline noreturn nosync nounwind readnone uwtable willreturn }
477 ; IS__TUNIT____: attributes #[[ATTR5:[0-9]+]] = { nofree noinline nounwind readnone uwtable }
478 ; IS__TUNIT____: attributes #[[ATTR6:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
479 ; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nounwind }
480 ; IS__TUNIT____: attributes #[[ATTR8:[0-9]+]] = { nobuiltin nofree nounwind }
481 ; IS__TUNIT____: attributes #[[ATTR9:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind willreturn }
482 ; IS__TUNIT____: attributes #[[ATTR10:[0-9]+]] = { nounwind willreturn }
483 ; IS__TUNIT____: attributes #[[ATTR11]] = { readnone willreturn }
484 ; IS__TUNIT____: attributes #[[ATTR12]] = { willreturn }
486 ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nounwind }
487 ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { noinline nounwind uwtable }
488 ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nobuiltin nounwind }
489 ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn }
490 ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nofree noinline noreturn nosync nounwind readnone uwtable willreturn }
491 ; IS__CGSCC_OPM: attributes #[[ATTR5:[0-9]+]] = { nofree noinline nounwind readnone uwtable }
492 ; IS__CGSCC_OPM: attributes #[[ATTR6:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
493 ; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nofree noinline nosync nounwind readnone uwtable willreturn }
494 ; IS__CGSCC_OPM: attributes #[[ATTR8]] = { nofree nounwind }
495 ; IS__CGSCC_OPM: attributes #[[ATTR9:[0-9]+]] = { nobuiltin nofree nounwind }
496 ; IS__CGSCC_OPM: attributes #[[ATTR10:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind willreturn }
497 ; IS__CGSCC_OPM: attributes #[[ATTR11:[0-9]+]] = { nounwind willreturn }
498 ; IS__CGSCC_OPM: attributes #[[ATTR12]] = { readnone willreturn }
499 ; IS__CGSCC_OPM: attributes #[[ATTR13]] = { willreturn }
501 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nounwind }
502 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { noinline nounwind uwtable }
503 ; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nobuiltin nounwind }
504 ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn }
505 ; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn }
506 ; IS__CGSCC_NPM: attributes #[[ATTR5:[0-9]+]] = { nofree noinline nounwind readnone uwtable }
507 ; IS__CGSCC_NPM: attributes #[[ATTR6:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
508 ; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nofree noinline nosync nounwind readnone uwtable willreturn }
509 ; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree nounwind }
510 ; IS__CGSCC_NPM: attributes #[[ATTR9:[0-9]+]] = { nobuiltin nofree nounwind }
511 ; IS__CGSCC_NPM: attributes #[[ATTR10:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind willreturn }
512 ; IS__CGSCC_NPM: attributes #[[ATTR11:[0-9]+]] = { nounwind willreturn }
513 ; IS__CGSCC_NPM: attributes #[[ATTR12]] = { readnone willreturn }
514 ; IS__CGSCC_NPM: attributes #[[ATTR13]] = { willreturn }