1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes 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 6 7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 8 9; Test cases specifically designed for the "nofree" function attribute. 10; We use FIXME's to indicate problems and missing attributes. 11 12; Free functions 13declare void @free(i8* nocapture) local_unnamed_addr #1 14declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #0 15declare void @_ZdaPv(i8*) local_unnamed_addr #2 16 17 18; TEST 1 (positive case) 19define 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:#.*]] { 23; IS__TUNIT____-NEXT: ret void 24; 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:#.*]] { 28; IS__CGSCC____-NEXT: ret void 29; 30 ret void 31} 32 33 34; TEST 2 (negative case) 35; Only free 36; void only_free(char* p) { 37; free(p); 38; } 39 40define 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:#.*]] { 44; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP0]]) [[ATTR0:#.*]] 45; CHECK-NEXT: ret void 46; 47 tail call void @free(i8* %0) #1 48 ret void 49} 50 51 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; } 61 62 63define 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 69; 70 tail call void @free_in_scc2(i8* %0) #1 71 ret void 72} 73 74 75define 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 89; 90 %cmp = icmp eq i8* %0, null 91 br i1 %cmp, label %rec, label %call 92call: 93 tail call void @free(i8* %0) #1 94 br label %end 95rec: 96 tail call void @free_in_scc1(i8* %0) 97 br label %end 98end: 99 ret void 100} 101 102 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; } 111 112 113define 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:#.*]] { 117; NOT_CGSCC_NPM-NEXT: unreachable 118; 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:#.*]] { 122; IS__CGSCC_NPM-NEXT: unreachable 123; 124 call void @mutual_recursion2() 125 ret void 126} 127 128define 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 133; 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 138; 139 call void @mutual_recursion1() 140 ret void 141} 142 143 144; TEST 5 145; C++ delete operation (negative case) 146; void delete_op (char p[]){ 147; delete [] p; 148; } 149 150define 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:#.*]] 158; CHECK-NEXT: br label [[TMP4]] 159; CHECK: 4: 160; CHECK-NEXT: ret void 161; 162 %2 = icmp eq i8* %0, null 163 br i1 %2, label %4, label %3 164 165; <label>:3: ; preds = %1 166 tail call void @_ZdaPv(i8* nonnull %0) #2 167 br label %4 168 169; <label>:4: ; preds = %3, %1 170 ret void 171} 172 173 174; TEST 6 (negative case) 175; Call realloc 176define 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]] 182; 183 %ret = tail call i8* @realloc(i8* %0, i64 %1) #2 184 ret i8* %ret 185} 186 187 188; TEST 7 (positive case) 189; Call function declaration with "nofree" 190 191 192; CHECK: Function Attrs: nofree noinline nounwind readnone uwtable 193; CHECK-NEXT: declare void @nofree_function() 194declare void @nofree_function() nofree readnone #0 195 196define 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 201; 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 206; 207 tail call void @nofree_function() 208 ret void 209} 210 211; TEST 8 (negative case) 212; Call function declaration without "nofree" 213 214 215; CHECK: Function Attrs: noinline nounwind uwtable 216; CHECK-NEXT: declare void @maybe_free() 217declare void @maybe_free() #0 218 219 220define 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 226; 227 tail call void @maybe_free() 228 ret void 229} 230 231 232; TEST 9 (negative case) 233; Call both of above functions 234 235define 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 241; 242 tail call void @maybe_free() 243 tail call void @nofree_function() 244 ret void 245} 246 247 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) 252declare float @llvm.floor.f32(float) 253 254define 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 259; 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 264; 265 tail call float @llvm.floor.f32(float %a) 266 ret void 267} 268 269define 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:#.*]] 274; IS__TUNIT____-NEXT: ret float [[C]] 275; 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:#.*]] { 279; IS__CGSCC____-NEXT: [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) [[ATTR12:#.*]] 280; IS__CGSCC____-NEXT: ret float [[C]] 281; 282 %c = tail call float @llvm.floor.f32(float %a) 283 ret float %c 284} 285 286; TEST 11 (positive case) 287; Check propagation. 288 289define 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 294; 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 299; 300 tail call void @nofree_function() 301 ret void 302} 303 304define 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 309; 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 314; 315 tail call void @f1() 316 ret void 317} 318 319; TEST 12 NoFree argument - positive. 320define double @test12(double* nocapture readonly %a) { 321; CHECK: Function Attrs: nofree nounwind 322; CHECK-LABEL: define {{[^@]+}}@test12 323; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) [[ATTR8:#.*]] { 324; CHECK-NEXT: entry: 325; CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[A]], align 8 326; CHECK-NEXT: [[CALL:%.*]] = tail call double @cos(double [[TMP0]]) [[ATTR2]] 327; CHECK-NEXT: ret double [[CALL]] 328; 329entry: 330 %0 = load double, double* %a, align 8 331 %call = tail call double @cos(double %0) #2 332 ret double %call 333} 334 335declare double @cos(double) nobuiltin nounwind nofree 336 337; FIXME: %a should be nofree. 338; TEST 13 NoFree argument - positive. 339define noalias i32* @test13(i64* nocapture readonly %a) { 340; CHECK: Function Attrs: nounwind 341; CHECK-LABEL: define {{[^@]+}}@test13 342; CHECK-SAME: (i64* nocapture nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) [[ATTR0]] { 343; CHECK-NEXT: entry: 344; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[A]], align 8 345; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @malloc(i64 [[TMP0]]) [[ATTR2]] 346; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[CALL]] to i32* 347; CHECK-NEXT: ret i32* [[TMP1]] 348; 349entry: 350 %0 = load i64, i64* %a, align 8 351 %call = tail call noalias i8* @malloc(i64 %0) #2 352 %1 = bitcast i8* %call to i32* 353 ret i32* %1 354} 355 356define void @test14(i8* nocapture %0, i8* nocapture %1) { 357; CHECK: Function Attrs: nounwind 358; CHECK-LABEL: define {{[^@]+}}@test14 359; CHECK-SAME: (i8* nocapture [[TMP0:%.*]], i8* nocapture nofree readnone [[TMP1:%.*]]) [[ATTR0]] { 360; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP0]]) [[ATTR0]] 361; CHECK-NEXT: ret void 362; 363 tail call void @free(i8* %0) #1 364 ret void 365} 366 367; UTC_ARGS: --enable 368 369define void @nonnull_assume_pos(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) { 370; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_pos 371; ATTRIBUTOR-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) 372; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #11 [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 373; ATTRIBUTOR-NEXT: call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]]) 374; ATTRIBUTOR-NEXT: ret void 375; 376; IS__TUNIT____-LABEL: define {{[^@]+}}@nonnull_assume_pos 377; IS__TUNIT____-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) { 378; IS__TUNIT____-NEXT: call void @llvm.assume(i1 noundef true) [[ATTR11]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 379; IS__TUNIT____-NEXT: call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]]) 380; IS__TUNIT____-NEXT: ret void 381; 382; IS__CGSCC____-LABEL: define {{[^@]+}}@nonnull_assume_pos 383; IS__CGSCC____-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) { 384; IS__CGSCC____-NEXT: call void @llvm.assume(i1 noundef true) [[ATTR12]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 385; IS__CGSCC____-NEXT: call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]]) 386; IS__CGSCC____-NEXT: ret void 387; 388 call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg3)] 389 call void @unknown(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) 390 ret void 391} 392define void @nonnull_assume_neg(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) { 393; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_neg 394; ATTRIBUTOR-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) 395; ATTRIBUTOR-NEXT: call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]]) 396; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 397; ATTRIBUTOR-NEXT: ret void 398; 399; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_neg 400; CHECK-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) { 401; CHECK-NEXT: call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]]) 402; CHECK-NEXT: call void @llvm.assume(i1 noundef true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 403; CHECK-NEXT: ret void 404; 405 call void @unknown(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) 406 call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg3)] 407 ret void 408} 409define void @nonnull_assume_call(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) { 410; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_call 411; ATTRIBUTOR-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) 412; ATTRIBUTOR-NEXT: call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]]) 413; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias readnone [[ARG1]]) 414; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias readnone [[ARG2]]) 415; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 416; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias nofree readnone [[ARG3]]) 417; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias readnone [[ARG4]]) 418; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(i8* noalias nofree readnone [[ARG1]]) 419; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(i8* noalias readnone [[ARG2]]) 420; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG4]]) ] 421; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(i8* noalias nofree readnone [[ARG3]]) 422; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(i8* noalias nofree readnone [[ARG4]]) 423; ATTRIBUTOR-NEXT: ret void 424; 425; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_call 426; CHECK-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) { 427; CHECK-NEXT: call void @unknown(i8* [[ARG1]], i8* [[ARG2]], i8* [[ARG3]], i8* [[ARG4]]) 428; CHECK-NEXT: call void @use_i8_ptr(i8* noalias nocapture readnone [[ARG1]]) [[ATTR0]] 429; CHECK-NEXT: call void @use_i8_ptr(i8* noalias nocapture readnone [[ARG2]]) [[ATTR0]] 430; CHECK-NEXT: call void @llvm.assume(i1 noundef true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ] 431; CHECK-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[ARG3]]) [[ATTR0]] 432; CHECK-NEXT: call void @use_i8_ptr(i8* noalias nocapture readnone [[ARG4]]) [[ATTR0]] 433; CHECK-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree readnone [[ARG1]]) [[ATTR0]] 434; CHECK-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture readnone [[ARG2]]) [[ATTR0]] 435; CHECK-NEXT: call void @llvm.assume(i1 noundef true) [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG4]]) ] 436; CHECK-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree readnone [[ARG3]]) [[ATTR0]] 437; CHECK-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree readnone [[ARG4]]) [[ATTR0]] 438; CHECK-NEXT: ret void 439; 440 call void @unknown(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) 441 call void @use_i8_ptr(i8* %arg1) 442 call void @use_i8_ptr(i8* %arg2) 443 call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg3)] 444 call void @use_i8_ptr(i8* %arg3) 445 call void @use_i8_ptr(i8* %arg4) 446 call void @use_i8_ptr_ret(i8* %arg1) 447 call void @use_i8_ptr_ret(i8* %arg2) 448 call void @llvm.assume(i1 true) ["nofree"(i8* %arg1), "nofree"(i8* %arg4)] 449 call void @use_i8_ptr_ret(i8* %arg3) 450 call void @use_i8_ptr_ret(i8* %arg4) 451 ret void 452} 453declare void @llvm.assume(i1) 454declare void @unknown(i8*, i8*, i8*, i8*) 455declare void @use_i8_ptr(i8* nocapture readnone) nounwind 456declare void @use_i8_ptr_ret(i8* nocapture readnone) nounwind willreturn 457 458declare noalias i8* @malloc(i64) 459 460attributes #0 = { nounwind uwtable noinline } 461attributes #1 = { nounwind } 462attributes #2 = { nobuiltin nounwind } 463