1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC 4 5declare noalias ptr @malloc(i64) allockind("alloc,uninitialized") allocsize(0) 6 7declare void @nocapture_func_frees_pointer(ptr nocapture) 8 9declare void @func_throws(...) 10 11declare void @sync_func(ptr %p) 12 13declare void @sync_will_return(ptr %p) willreturn nounwind 14 15declare void @no_sync_func(ptr nocapture %p) nofree nosync willreturn 16 17declare void @nofree_func(ptr nocapture %p) nofree nosync willreturn 18 19declare void @foo(ptr %p) 20 21declare void @foo_nounw(ptr %p) nounwind nofree 22 23declare void @usei8(i8) 24declare void @usei8p(ptr nocapture) 25 26declare i32 @no_return_call() noreturn 27 28declare void @free(ptr nocapture) allockind("free") 29 30declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind 31 32;. 33; CHECK: @G = internal global ptr undef, align 4 34;. 35define void @h2s_value_simplify_interaction(i1 %c, ptr %A) { 36; CHECK-LABEL: define {{[^@]+}}@h2s_value_simplify_interaction 37; CHECK-SAME: (i1 [[C:%.*]], ptr nofree readnone captures(none) [[A:%.*]]) { 38; CHECK-NEXT: entry: 39; CHECK-NEXT: [[ADD:%.*]] = add i64 2, 2 40; CHECK-NEXT: [[M:%.*]] = tail call noalias align 16 ptr @malloc(i64 noundef [[ADD]]) 41; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 42; CHECK: t: 43; CHECK-NEXT: br i1 false, label [[DEAD:%.*]], label [[F2:%.*]] 44; CHECK: f: 45; CHECK-NEXT: br label [[J:%.*]] 46; CHECK: f2: 47; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[M]], align 16 48; CHECK-NEXT: call void @usei8(i8 [[L]]) 49; CHECK-NEXT: call void @no_sync_func(ptr noalias nofree noundef nonnull align 16 captures(none) dereferenceable(1) [[M]]) #[[ATTR11:[0-9]+]] 50; CHECK-NEXT: br label [[J]] 51; CHECK: dead: 52; CHECK-NEXT: unreachable 53; CHECK: j: 54; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[M]], [[F]] ], [ null, [[F2]] ] 55; CHECK-NEXT: tail call void @no_sync_func(ptr nofree noundef align 16 captures(none) [[PHI]]) #[[ATTR11]] 56; CHECK-NEXT: ret void 57; 58entry: 59 %add = add i64 2, 2 60 %m = tail call noalias align 16 ptr @malloc(i64 %add) 61 br i1 %c, label %t, label %f 62 63t: 64 br i1 false, label %dead, label %f2 65 66f: 67 br label %j 68 69f2: 70 %l = load i8, ptr %m, align 1 71 call void @usei8(i8 %l) 72 call void @no_sync_func(ptr noundef %m) nounwind 73 br label %j 74 75dead: 76 br label %j 77 78j: 79 %phi = phi ptr [ %m, %f ], [ null, %f2 ], [ %A, %dead ] 80 tail call void @no_sync_func(ptr noundef %phi) nounwind 81 ret void 82} 83 84define void @nofree_arg_only(ptr %p1, ptr %p2) { 85; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only 86; CHECK-SAME: (ptr nofree captures(none) [[P1:%.*]], ptr captures(none) [[P2:%.*]]) { 87; CHECK-NEXT: bb: 88; CHECK-NEXT: tail call void @free(ptr captures(none) [[P2]]) 89; CHECK-NEXT: tail call void @nofree_func(ptr nofree captures(none) [[P1]]) 90; CHECK-NEXT: ret void 91; 92bb: 93 tail call void @free(ptr %p2) 94 tail call void @nofree_func(ptr %p1) 95 ret void 96} 97 98; TEST 1 - negative, pointer freed in another function. 99 100define void @test1() { 101; CHECK-LABEL: define {{[^@]+}}@test1() { 102; CHECK-NEXT: bb: 103; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 104; CHECK-NEXT: tail call void @nocapture_func_frees_pointer(ptr noalias captures(none) [[I]]) 105; CHECK-NEXT: tail call void (...) @func_throws() 106; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]]) 107; CHECK-NEXT: ret void 108; 109bb: 110 %i = tail call noalias ptr @malloc(i64 4) 111 tail call void @nocapture_func_frees_pointer(ptr %i) 112 tail call void (...) @func_throws() 113 tail call void @free(ptr %i) 114 ret void 115} 116 117; TEST 2 - negative, call to a sync function. 118 119define void @test2() { 120; CHECK-LABEL: define {{[^@]+}}@test2() { 121; CHECK-NEXT: bb: 122; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 123; CHECK-NEXT: tail call void @sync_func(ptr [[I]]) 124; CHECK-NEXT: tail call void @free(ptr captures(none) [[I]]) 125; CHECK-NEXT: ret void 126; 127bb: 128 %i = tail call noalias ptr @malloc(i64 4) 129 tail call void @sync_func(ptr %i) 130 tail call void @free(ptr %i) 131 ret void 132} 133 134; TEST 3 - 1 malloc, 1 free 135 136define void @test3() { 137; CHECK-LABEL: define {{[^@]+}}@test3() { 138; CHECK-NEXT: bb: 139; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 140; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]]) 141; CHECK-NEXT: ret void 142; 143bb: 144 %i = tail call noalias ptr @malloc(i64 4) 145 tail call void @no_sync_func(ptr %i) 146 tail call void @free(ptr %i) 147 ret void 148} 149 150define void @test3a(ptr %p) { 151; CHECK-LABEL: define {{[^@]+}}@test3a 152; CHECK-SAME: (ptr captures(none) [[P:%.*]]) { 153; CHECK-NEXT: bb: 154; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 155; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I_H2S]], ptr captures(none) [[P]]) 156; CHECK-NEXT: ret void 157; 158bb: 159 %i = tail call noalias ptr @malloc(i64 4) 160 tail call void @nofree_arg_only(ptr %i, ptr %p) 161 tail call void @free(ptr %i) 162 ret void 163} 164 165declare noalias ptr @aligned_alloc(i64 allocalign, i64) allockind("alloc,uninitialized,aligned") allocsize(1) 166 167define void @test3b(ptr %p) { 168; CHECK-LABEL: define {{[^@]+}}@test3b 169; CHECK-SAME: (ptr captures(none) [[P:%.*]]) { 170; CHECK-NEXT: bb: 171; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 128, align 32 172; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I_H2S]], ptr captures(none) [[P]]) 173; CHECK-NEXT: ret void 174; 175bb: 176 %i = tail call noalias ptr @aligned_alloc(i64 32, i64 128) 177 tail call void @nofree_arg_only(ptr %i, ptr %p) 178 tail call void @free(ptr %i) 179 ret void 180} 181 182; leave alone non-constant alignments. 183define void @test3c(i64 %alignment) { 184; CHECK-LABEL: define {{[^@]+}}@test3c 185; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) { 186; CHECK-NEXT: bb: 187; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128) 188; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]]) 189; CHECK-NEXT: ret void 190; 191bb: 192 %i = tail call noalias ptr @aligned_alloc(i64 %alignment, i64 128) 193 tail call void @free(ptr %i) 194 ret void 195} 196 197; leave alone a constant-but-invalid alignment 198define void @test3d(ptr %p) { 199; CHECK-LABEL: define {{[^@]+}}@test3d 200; CHECK-SAME: (ptr captures(none) [[P:%.*]]) { 201; CHECK-NEXT: bb: 202; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @aligned_alloc(i64 noundef 33, i64 noundef 128) 203; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I]], ptr captures(none) [[P]]) 204; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]]) 205; CHECK-NEXT: ret void 206; 207bb: 208 %i = tail call noalias ptr @aligned_alloc(i64 33, i64 128) 209 tail call void @nofree_arg_only(ptr %i, ptr %p) 210 tail call void @free(ptr %i) 211 ret void 212} 213 214declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1) 215 216define void @test0() { 217; CHECK-LABEL: define {{[^@]+}}@test0() { 218; CHECK-NEXT: bb: 219; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 8, align 1 220; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[I_H2S]], i8 0, i64 8, i1 false) 221; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]]) 222; CHECK-NEXT: ret void 223; 224bb: 225 %i = tail call noalias ptr @calloc(i64 2, i64 4) 226 tail call void @no_sync_func(ptr %i) 227 tail call void @free(ptr %i) 228 ret void 229} 230 231; TEST 4 232define void @test4() { 233; CHECK-LABEL: define {{[^@]+}}@test4() { 234; CHECK-NEXT: bb: 235; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 236; CHECK-NEXT: tail call void @nofree_func(ptr noalias nofree captures(none) [[I_H2S]]) 237; CHECK-NEXT: ret void 238; 239bb: 240 %i = tail call noalias ptr @malloc(i64 4) 241 tail call void @nofree_func(ptr %i) 242 ret void 243} 244 245; TEST 5 - not all exit paths have a call to free, but all uses of malloc 246; are in nofree functions and are not captured 247 248define void @test5(i32 %arg, ptr %p) { 249; CHECK-LABEL: define {{[^@]+}}@test5 250; CHECK-SAME: (i32 [[ARG:%.*]], ptr captures(none) [[P:%.*]]) { 251; CHECK-NEXT: bb: 252; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 253; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[ARG]], 0 254; CHECK-NEXT: br i1 [[I1]], label [[BB3:%.*]], label [[BB2:%.*]] 255; CHECK: bb2: 256; CHECK-NEXT: tail call void @nofree_func(ptr noalias nofree captures(none) [[I_H2S]]) 257; CHECK-NEXT: br label [[BB4:%.*]] 258; CHECK: bb3: 259; CHECK-NEXT: tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I_H2S]], ptr captures(none) [[P]]) 260; CHECK-NEXT: br label [[BB4]] 261; CHECK: bb4: 262; CHECK-NEXT: ret void 263; 264bb: 265 %i = tail call noalias ptr @malloc(i64 4) 266 %i1 = icmp eq i32 %arg, 0 267 br i1 %i1, label %bb3, label %bb2 268 269bb2: 270 tail call void @nofree_func(ptr %i) 271 br label %bb4 272 273bb3: 274 tail call void @nofree_arg_only(ptr %i, ptr %p) 275 tail call void @free(ptr %i) 276 br label %bb4 277 278bb4: 279 ret void 280} 281 282; TEST 6 - all exit paths have a call to free 283 284define void @test6(i32 %arg) { 285; CHECK-LABEL: define {{[^@]+}}@test6 286; CHECK-SAME: (i32 [[ARG:%.*]]) { 287; CHECK-NEXT: bb: 288; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 289; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[ARG]], 0 290; CHECK-NEXT: br i1 [[I1]], label [[BB3:%.*]], label [[BB2:%.*]] 291; CHECK: bb2: 292; CHECK-NEXT: tail call void @nofree_func(ptr noalias nofree captures(none) [[I_H2S]]) 293; CHECK-NEXT: br label [[BB4:%.*]] 294; CHECK: bb3: 295; CHECK-NEXT: br label [[BB4]] 296; CHECK: bb4: 297; CHECK-NEXT: ret void 298; 299bb: 300 %i = tail call noalias ptr @malloc(i64 4) 301 %i1 = icmp eq i32 %arg, 0 302 br i1 %i1, label %bb3, label %bb2 303 304bb2: 305 tail call void @nofree_func(ptr %i) 306 tail call void @free(ptr %i) 307 br label %bb4 308 309bb3: 310 tail call void @free(ptr %i) 311 br label %bb4 312 313bb4: 314 ret void 315} 316 317; TEST 7 - free is dead. 318 319define void @test7() { 320; CHECK-LABEL: define {{[^@]+}}@test7() { 321; CHECK-NEXT: bb: 322; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 323; CHECK-NEXT: [[I1:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]] 324; CHECK-NEXT: unreachable 325; 326bb: 327 %i = tail call noalias ptr @malloc(i64 4) 328 %i1 = tail call i32 @no_return_call() 329 tail call void @free(ptr %i) 330 ret void 331} 332 333; TEST 8 - Negative: bitcast pointer used in capture function 334 335define void @test8() { 336; CHECK-LABEL: define {{[^@]+}}@test8() { 337; CHECK-NEXT: bb: 338; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 339; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]]) 340; CHECK-NEXT: store i32 10, ptr [[I]], align 4 341; CHECK-NEXT: tail call void @foo(ptr nonnull align 4 dereferenceable(4) [[I]]) 342; CHECK-NEXT: tail call void @free(ptr nonnull align 4 captures(none) dereferenceable(4) [[I]]) 343; CHECK-NEXT: ret void 344; 345bb: 346 %i = tail call noalias ptr @malloc(i64 4) 347 tail call void @no_sync_func(ptr %i) 348 store i32 10, ptr %i, align 4 349 %i2 = load i32, ptr %i, align 4 350 tail call void @foo(ptr %i) 351 tail call void @free(ptr %i) 352 ret void 353} 354 355; TEST 9 - FIXME: malloc should be converted. 356define void @test9() { 357; CHECK-LABEL: define {{[^@]+}}@test9() { 358; CHECK-NEXT: bb: 359; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 360; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]]) 361; CHECK-NEXT: store i32 10, ptr [[I]], align 4 362; CHECK-NEXT: tail call void @foo_nounw(ptr nofree nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR11]] 363; CHECK-NEXT: tail call void @free(ptr nonnull align 4 captures(none) dereferenceable(4) [[I]]) 364; CHECK-NEXT: ret void 365; 366bb: 367 %i = tail call noalias ptr @malloc(i64 4) 368 tail call void @no_sync_func(ptr %i) 369 store i32 10, ptr %i, align 4 370 %i2 = load i32, ptr %i, align 4 371 tail call void @foo_nounw(ptr %i) 372 tail call void @free(ptr %i) 373 ret void 374} 375 376; TEST 10 - 1 malloc, 1 free 377 378define i32 @test10() { 379; CHECK-LABEL: define {{[^@]+}}@test10() { 380; CHECK-NEXT: bb: 381; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 382; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]]) 383; CHECK-NEXT: store i32 10, ptr [[I_H2S]], align 4 384; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I_H2S]], align 4 385; CHECK-NEXT: ret i32 [[I2]] 386; 387bb: 388 %i = tail call noalias ptr @malloc(i64 4) 389 tail call void @no_sync_func(ptr %i) 390 store i32 10, ptr %i, align 4 391 %i2 = load i32, ptr %i, align 4 392 tail call void @free(ptr %i) 393 ret i32 %i2 394} 395 396define i32 @test_lifetime() { 397; CHECK-LABEL: define {{[^@]+}}@test_lifetime() { 398; CHECK-NEXT: bb: 399; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 400; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]]) 401; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nofree nonnull align 4 captures(none) dereferenceable(4) [[I_H2S]]) 402; CHECK-NEXT: store i32 10, ptr [[I_H2S]], align 4 403; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I_H2S]], align 4 404; CHECK-NEXT: ret i32 [[I2]] 405; 406bb: 407 %i = tail call noalias ptr @malloc(i64 4) 408 tail call void @no_sync_func(ptr %i) 409 call void @llvm.lifetime.start.p0(i64 4, ptr %i) 410 store i32 10, ptr %i, align 4 411 %i2 = load i32, ptr %i, align 4 412 tail call void @free(ptr %i) 413 ret i32 %i2 414} 415 416; TEST 11 417 418define void @test11() { 419; CHECK-LABEL: define {{[^@]+}}@test11() { 420; CHECK-NEXT: bb: 421; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 422; CHECK-NEXT: tail call void @sync_will_return(ptr [[I_H2S]]) #[[ATTR11]] 423; CHECK-NEXT: ret void 424; 425bb: 426 %i = tail call noalias ptr @malloc(i64 4) 427 tail call void @sync_will_return(ptr %i) 428 tail call void @free(ptr %i) 429 ret void 430} 431 432; TEST 12 433define i32 @irreducible_cfg(i32 %arg) { 434; CHECK-LABEL: define {{[^@]+}}@irreducible_cfg 435; CHECK-SAME: (i32 [[ARG:%.*]]) { 436; CHECK-NEXT: bb: 437; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 438; CHECK-NEXT: store i32 10, ptr [[I_H2S]], align 4 439; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[ARG]], 1 440; CHECK-NEXT: br i1 [[I2]], label [[BB3:%.*]], label [[BB5:%.*]] 441; CHECK: bb3: 442; CHECK-NEXT: [[I4:%.*]] = add nsw i32 [[ARG]], 5 443; CHECK-NEXT: br label [[BB11:%.*]] 444; CHECK: bb5: 445; CHECK-NEXT: br label [[BB6:%.*]] 446; CHECK: bb6: 447; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[I12:%.*]], [[BB11]] ], [ 1, [[BB5]] ] 448; CHECK-NEXT: [[I7:%.*]] = load i32, ptr [[I_H2S]], align 4 449; CHECK-NEXT: [[I8:%.*]] = add nsw i32 [[I7]], -1 450; CHECK-NEXT: store i32 [[I8]], ptr [[I_H2S]], align 4 451; CHECK-NEXT: [[I9:%.*]] = icmp ne i32 [[I7]], 0 452; CHECK-NEXT: br i1 [[I9]], label [[BB10:%.*]], label [[BB13:%.*]] 453; CHECK: bb10: 454; CHECK-NEXT: br label [[BB11]] 455; CHECK: bb11: 456; CHECK-NEXT: [[DOT1:%.*]] = phi i32 [ [[I4]], [[BB3]] ], [ [[DOT0]], [[BB10]] ] 457; CHECK-NEXT: [[I12]] = add nsw i32 [[DOT1]], 1 458; CHECK-NEXT: br label [[BB6]] 459; CHECK: bb13: 460; CHECK-NEXT: [[I16:%.*]] = load i32, ptr [[I_H2S]], align 4 461; CHECK-NEXT: ret i32 [[I16]] 462; 463bb: 464 %i = call noalias ptr @malloc(i64 4) 465 store i32 10, ptr %i, align 4 466 %i2 = icmp eq i32 %arg, 1 467 br i1 %i2, label %bb3, label %bb5 468 469bb3: 470 %i4 = add nsw i32 %arg, 5 471 br label %bb11 472 473bb5: 474 br label %bb6 475 476bb6: 477 %.0 = phi i32 [ %i12, %bb11 ], [ 1, %bb5 ] 478 %i7 = load i32, ptr %i, align 4 479 %i8 = add nsw i32 %i7, -1 480 store i32 %i8, ptr %i, align 4 481 %i9 = icmp ne i32 %i7, 0 482 br i1 %i9, label %bb10, label %bb13 483 484bb10: 485 br label %bb11 486 487bb11: 488 %.1 = phi i32 [ %i4, %bb3 ], [ %.0, %bb10 ] 489 %i12 = add nsw i32 %.1, 1 490 br label %bb6 491 492bb13: 493 %i14 = load i32, ptr %i, align 4 494 call void @free(ptr %i) 495 %i16 = load i32, ptr %i, align 4 496 ret i32 %i16 497} 498 499 500define i32 @malloc_in_loop(i32 %arg) { 501; CHECK-LABEL: define {{[^@]+}}@malloc_in_loop 502; CHECK-SAME: (i32 [[ARG:%.*]]) { 503; CHECK-NEXT: bb: 504; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 505; CHECK-NEXT: [[I1:%.*]] = alloca ptr, align 8 506; CHECK-NEXT: [[I11:%.*]] = alloca i8, i32 0, align 8 507; CHECK-NEXT: store i32 [[ARG]], ptr [[I]], align 4 508; CHECK-NEXT: br label [[BB2:%.*]] 509; CHECK: bb2: 510; CHECK-NEXT: [[I3:%.*]] = load i32, ptr [[I]], align 4 511; CHECK-NEXT: [[I4:%.*]] = add nsw i32 [[I3]], -1 512; CHECK-NEXT: store i32 [[I4]], ptr [[I]], align 4 513; CHECK-NEXT: [[I5:%.*]] = icmp sgt i32 [[I4]], 0 514; CHECK-NEXT: br i1 [[I5]], label [[BB6:%.*]], label [[BB9:%.*]] 515; CHECK: bb6: 516; CHECK-NEXT: [[I7_H2S:%.*]] = alloca i8, i64 4, align 1 517; CHECK-NEXT: br label [[BB2]] 518; CHECK: bb9: 519; CHECK-NEXT: ret i32 5 520; 521bb: 522 %i = alloca i32, align 4 523 %i1 = alloca ptr, align 8 524 store i32 %arg, ptr %i, align 4 525 br label %bb2 526 527bb2: 528 %i3 = load i32, ptr %i, align 4 529 %i4 = add nsw i32 %i3, -1 530 store i32 %i4, ptr %i, align 4 531 %i5 = icmp sgt i32 %i4, 0 532 br i1 %i5, label %bb6, label %bb9 533 534bb6: 535 %i7 = call noalias ptr @malloc(i64 4) 536 store i32 1, ptr %i7, align 8 537 br label %bb2 538 539bb9: 540 ret i32 5 541} 542 543; Malloc/Calloc too large 544define i32 @test13() { 545; CHECK-LABEL: define {{[^@]+}}@test13() { 546; CHECK-NEXT: bb: 547; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 256) 548; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]]) 549; CHECK-NEXT: store i32 10, ptr [[I]], align 4 550; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4 551; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]]) 552; CHECK-NEXT: ret i32 [[I2]] 553; 554bb: 555 %i = tail call noalias ptr @malloc(i64 256) 556 tail call void @no_sync_func(ptr %i) 557 store i32 10, ptr %i, align 4 558 %i2 = load i32, ptr %i, align 4 559 tail call void @free(ptr %i) 560 ret i32 %i2 561} 562 563define i32 @test_sle() { 564; CHECK-LABEL: define {{[^@]+}}@test_sle() { 565; CHECK-NEXT: bb: 566; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef -1) 567; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]]) 568; CHECK-NEXT: store i32 10, ptr [[I]], align 4 569; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4 570; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]]) 571; CHECK-NEXT: ret i32 [[I2]] 572; 573bb: 574 %i = tail call noalias ptr @malloc(i64 -1) 575 tail call void @no_sync_func(ptr %i) 576 store i32 10, ptr %i, align 4 577 %i2 = load i32, ptr %i, align 4 578 tail call void @free(ptr %i) 579 ret i32 %i2 580} 581 582define i32 @test_overflow() { 583; CHECK-LABEL: define {{[^@]+}}@test_overflow() { 584; CHECK-NEXT: bb: 585; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 65537, i64 noundef 65537) 586; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]]) 587; CHECK-NEXT: store i32 10, ptr [[I]], align 4 588; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4 589; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]]) 590; CHECK-NEXT: ret i32 [[I2]] 591; 592bb: 593 %i = tail call noalias ptr @calloc(i64 65537, i64 65537) 594 tail call void @no_sync_func(ptr %i) 595 store i32 10, ptr %i, align 4 596 %i2 = load i32, ptr %i, align 4 597 tail call void @free(ptr %i) 598 ret i32 %i2 599} 600 601define void @test14() { 602; CHECK-LABEL: define {{[^@]+}}@test14() { 603; CHECK-NEXT: bb: 604; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 64, i64 noundef 4) 605; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]]) 606; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]]) 607; CHECK-NEXT: ret void 608; 609bb: 610 %i = tail call noalias ptr @calloc(i64 64, i64 4) 611 tail call void @no_sync_func(ptr %i) 612 tail call void @free(ptr %i) 613 ret void 614} 615 616define void @test15(i64 %S) { 617; CHECK-LABEL: define {{[^@]+}}@test15 618; CHECK-SAME: (i64 [[S:%.*]]) { 619; CHECK-NEXT: bb: 620; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 [[S]]) 621; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]]) 622; CHECK-NEXT: tail call void @free(ptr noalias captures(none) [[I]]) 623; CHECK-NEXT: ret void 624; 625bb: 626 %i = tail call noalias ptr @malloc(i64 %S) 627 tail call void @no_sync_func(ptr %i) 628 tail call void @free(ptr %i) 629 ret void 630} 631 632define void @test16a(i8 %v, ptr %P) { 633; CHECK-LABEL: define {{[^@]+}}@test16a 634; CHECK-SAME: (i8 [[V:%.*]], ptr nofree readnone captures(none) [[P:%.*]]) { 635; CHECK-NEXT: bb: 636; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 637; CHECK-NEXT: store i8 [[V]], ptr [[I_H2S]], align 1 638; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree noundef nonnull captures(none) dereferenceable(1) [[I_H2S]]) 639; CHECK-NEXT: ret void 640; 641bb: 642 %i = tail call noalias ptr @malloc(i64 4) 643 store i8 %v, ptr %i, align 1 644 tail call void @no_sync_func(ptr %i) 645 tail call void @free(ptr nonnull dereferenceable(1) %i) 646 ret void 647} 648 649define void @test16b(i8 %v, ptr %P) { 650; CHECK-LABEL: define {{[^@]+}}@test16b 651; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) { 652; CHECK-NEXT: bb: 653; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 654; CHECK-NEXT: store ptr [[I]], ptr [[P]], align 8 655; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I]]) 656; CHECK-NEXT: tail call void @free(ptr captures(none) [[I]]) 657; CHECK-NEXT: ret void 658; 659bb: 660 %i = tail call noalias ptr @malloc(i64 4) 661 store ptr %i, ptr %P, align 8 662 tail call void @no_sync_func(ptr %i) 663 tail call void @free(ptr %i) 664 ret void 665} 666 667define void @test16c(i8 %v, ptr %P) { 668; CHECK-LABEL: define {{[^@]+}}@test16c 669; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) { 670; CHECK-NEXT: bb: 671; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 672; CHECK-NEXT: store ptr [[I_H2S]], ptr [[P]], align 8 673; CHECK-NEXT: tail call void @no_sync_func(ptr nofree captures(none) [[I_H2S]]) #[[ATTR11]] 674; CHECK-NEXT: ret void 675; 676bb: 677 %i = tail call noalias ptr @malloc(i64 4) 678 store ptr %i, ptr %P, align 8 679 tail call void @no_sync_func(ptr %i) nounwind 680 tail call void @free(ptr %i) 681 ret void 682} 683 684define void @test16d(i8 %v, ptr %P) { 685; CHECK-LABEL: define {{[^@]+}}@test16d 686; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) { 687; CHECK-NEXT: bb: 688; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) 689; CHECK-NEXT: store ptr [[I]], ptr [[P]], align 8 690; CHECK-NEXT: ret void 691; 692bb: 693 %i = tail call noalias ptr @malloc(i64 4) 694 store ptr %i, ptr %P, align 8 695 ret void 696} 697 698@G = internal global ptr undef, align 4 699define void @test16e(i8 %v) norecurse { 700; CHECK: Function Attrs: norecurse 701; CHECK-LABEL: define {{[^@]+}}@test16e 702; CHECK-SAME: (i8 [[V:%.*]]) #[[ATTR9:[0-9]+]] { 703; CHECK-NEXT: bb: 704; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1 705; CHECK-NEXT: store ptr [[I_H2S]], ptr @G, align 8 706; CHECK-NEXT: call void @usei8p(ptr nofree captures(none) [[I_H2S]]) #[[ATTR12:[0-9]+]] 707; CHECK-NEXT: ret void 708; 709bb: 710 %i = tail call noalias ptr @malloc(i64 4) 711 store ptr %i, ptr @G, align 8 712 %i1 = load ptr, ptr @G, align 8 713 call void @usei8p(ptr nocapture nofree %i1) nocallback nosync nounwind willreturn 714 call void @free(ptr %i) 715 ret void 716} 717 718;. 719; CHECK: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) } 720; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn } 721; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn } 722; CHECK: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind } 723; CHECK: attributes #[[ATTR4]] = { noreturn } 724; CHECK: attributes #[[ATTR5:[0-9]+]] = { allockind("free") } 725; CHECK: attributes #[[ATTR6:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } 726; CHECK: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) } 727; CHECK: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) } 728; CHECK: attributes #[[ATTR9]] = { norecurse } 729; CHECK: attributes #[[ATTR10:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) } 730; CHECK: attributes #[[ATTR11]] = { nounwind } 731; CHECK: attributes #[[ATTR12]] = { nocallback nosync nounwind willreturn } 732;. 733;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 734; CGSCC: {{.*}} 735; TUNIT: {{.*}} 736