1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes 2; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -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-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -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 -attributor-manifest-internal -attributor-disable=false -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-disable=false -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 7declare noalias i8* @malloc(i64) 8 9declare void @nocapture_func_frees_pointer(i8* nocapture) 10 11declare void @func_throws(...) 12 13declare void @sync_func(i8* %p) 14 15declare void @sync_will_return(i8* %p) willreturn nounwind 16 17declare void @no_sync_func(i8* nocapture %p) nofree nosync willreturn 18 19declare void @nofree_func(i8* nocapture %p) nofree nosync willreturn 20 21declare void @foo(i32* %p) 22 23declare void @foo_nounw(i32* %p) nounwind nofree 24 25declare i32 @no_return_call() noreturn 26 27declare void @free(i8* nocapture) 28 29declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind 30 31define void @nofree_arg_only(i8* %p1, i8* %p2) { 32; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only 33; CHECK-SAME: (i8* nocapture nofree [[P1:%.*]], i8* nocapture [[P2:%.*]]) 34; CHECK-NEXT: tail call void @free(i8* nocapture [[P2]]) 35; CHECK-NEXT: tail call void @nofree_func(i8* nocapture nofree [[P1]]) 36; CHECK-NEXT: ret void 37; 38 tail call void @free(i8* %p2) 39 tail call void @nofree_func(i8* %p1) 40 ret void 41} 42 43; TEST 1 - negative, pointer freed in another function. 44 45define void @test1() { 46; IS________OPM-LABEL: define {{[^@]+}}@test1() 47; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 48; IS________OPM-NEXT: tail call void @nocapture_func_frees_pointer(i8* noalias [[TMP1]]) 49; IS________OPM-NEXT: tail call void (...) @func_throws() 50; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 51; IS________OPM-NEXT: ret void 52; 53; IS________NPM-LABEL: define {{[^@]+}}@test1() 54; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 55; IS________NPM-NEXT: tail call void @nocapture_func_frees_pointer(i8* noalias nocapture [[TMP1]]) 56; IS________NPM-NEXT: tail call void (...) @func_throws() 57; IS________NPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 58; IS________NPM-NEXT: ret void 59; 60 %1 = tail call noalias i8* @malloc(i64 4) 61 tail call void @nocapture_func_frees_pointer(i8* %1) 62 tail call void (...) @func_throws() 63 tail call void @free(i8* %1) 64 ret void 65} 66 67; TEST 2 - negative, call to a sync function. 68 69define void @test2() { 70; CHECK-LABEL: define {{[^@]+}}@test2() 71; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 72; CHECK-NEXT: tail call void @sync_func(i8* [[TMP1]]) 73; CHECK-NEXT: tail call void @free(i8* [[TMP1]]) 74; CHECK-NEXT: ret void 75; 76 %1 = tail call noalias i8* @malloc(i64 4) 77 tail call void @sync_func(i8* %1) 78 tail call void @free(i8* %1) 79 ret void 80} 81 82; TEST 3 - 1 malloc, 1 free 83 84define void @test3() { 85; IS________OPM-LABEL: define {{[^@]+}}@test3() 86; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 87; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 88; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 89; IS________OPM-NEXT: ret void 90; 91; IS________NPM-LABEL: define {{[^@]+}}@test3() 92; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 93; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 94; IS________NPM-NEXT: ret void 95; 96 %1 = tail call noalias i8* @malloc(i64 4) 97 tail call void @no_sync_func(i8* %1) 98 tail call void @free(i8* %1) 99 ret void 100} 101 102define void @test3a(i8* %p) { 103; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test3a 104; IS__TUNIT_OPM-SAME: (i8* nocapture [[P:%.*]]) 105; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 106; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) 107; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 108; IS__TUNIT_OPM-NEXT: ret void 109; 110; IS________NPM-LABEL: define {{[^@]+}}@test3a 111; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) 112; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 113; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) 114; IS________NPM-NEXT: ret void 115; 116; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test3a 117; IS__CGSCC_OPM-SAME: (i8* nocapture [[P:%.*]]) 118; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 119; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nofree [[TMP1]], i8* nocapture [[P]]) 120; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 121; IS__CGSCC_OPM-NEXT: ret void 122; 123 %1 = tail call noalias i8* @malloc(i64 4) 124 tail call void @nofree_arg_only(i8* %1, i8* %p) 125 tail call void @free(i8* %1) 126 ret void 127} 128 129declare noalias i8* @aligned_alloc(i64, i64) 130 131define void @test3b(i8* %p) { 132; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test3b 133; IS__TUNIT_OPM-SAME: (i8* nocapture [[P:%.*]]) 134; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 32, i64 128) 135; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) 136; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 137; IS__TUNIT_OPM-NEXT: ret void 138; 139; IS________NPM-LABEL: define {{[^@]+}}@test3b 140; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) 141; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 128, align 32 142; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) 143; IS________NPM-NEXT: ret void 144; 145; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test3b 146; IS__CGSCC_OPM-SAME: (i8* nocapture [[P:%.*]]) 147; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 32, i64 128) 148; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nofree [[TMP1]], i8* nocapture [[P]]) 149; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 150; IS__CGSCC_OPM-NEXT: ret void 151; 152 %1 = tail call noalias i8* @aligned_alloc(i64 32, i64 128) 153 tail call void @nofree_arg_only(i8* %1, i8* %p) 154 tail call void @free(i8* %1) 155 ret void 156} 157 158; leave alone non-constant alignments. 159define void @test3c(i64 %alignment) { 160; CHECK-LABEL: define {{[^@]+}}@test3c 161; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) 162; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 [[ALIGNMENT]], i64 128) 163; CHECK-NEXT: tail call void @free(i8* noalias [[TMP1]]) 164; CHECK-NEXT: ret void 165; 166 %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128) 167 tail call void @free(i8* %1) 168 ret void 169} 170 171declare noalias i8* @calloc(i64, i64) 172 173define void @test0() { 174; IS________OPM-LABEL: define {{[^@]+}}@test0() 175; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 2, i64 4) 176; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 177; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) 178; IS________OPM-NEXT: ret void 179; 180; IS________NPM-LABEL: define {{[^@]+}}@test0() 181; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 8 182; IS________NPM-NEXT: [[CALLOC_BC:%.*]] = bitcast i8* [[TMP1]] to i8* 183; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 8, i1 false) 184; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 185; IS________NPM-NEXT: ret void 186; 187 %1 = tail call noalias i8* @calloc(i64 2, i64 4) 188 tail call void @no_sync_func(i8* %1) 189 tail call void @free(i8* %1) 190 ret void 191} 192 193; TEST 4 194define void @test4() { 195; IS________OPM-LABEL: define {{[^@]+}}@test4() 196; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 197; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP1]]) 198; IS________OPM-NEXT: ret void 199; 200; IS________NPM-LABEL: define {{[^@]+}}@test4() 201; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 202; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP1]]) 203; IS________NPM-NEXT: ret void 204; 205 %1 = tail call noalias i8* @malloc(i64 4) 206 tail call void @nofree_func(i8* %1) 207 ret void 208} 209 210; TEST 5 - not all exit paths have a call to free, but all uses of malloc 211; are in nofree functions and are not captured 212 213define void @test5(i32, i8* %p) { 214; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test5 215; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) 216; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) 217; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 218; IS__TUNIT_OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 219; IS__TUNIT_OPM: 4: 220; IS__TUNIT_OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP2]]) 221; IS__TUNIT_OPM-NEXT: br label [[TMP6:%.*]] 222; IS__TUNIT_OPM: 5: 223; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]]) 224; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) 225; IS__TUNIT_OPM-NEXT: br label [[TMP6]] 226; IS__TUNIT_OPM: 6: 227; IS__TUNIT_OPM-NEXT: ret void 228; 229; IS________NPM-LABEL: define {{[^@]+}}@test5 230; IS________NPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) 231; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4 232; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 233; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 234; IS________NPM: 4: 235; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) 236; IS________NPM-NEXT: br label [[TMP6:%.*]] 237; IS________NPM: 5: 238; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP2]], i8* nocapture [[P]]) 239; IS________NPM-NEXT: br label [[TMP6]] 240; IS________NPM: 6: 241; IS________NPM-NEXT: ret void 242; 243; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test5 244; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) 245; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) 246; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 247; IS__CGSCC_OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 248; IS__CGSCC_OPM: 4: 249; IS__CGSCC_OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP2]]) 250; IS__CGSCC_OPM-NEXT: br label [[TMP6:%.*]] 251; IS__CGSCC_OPM: 5: 252; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nofree [[TMP2]], i8* nocapture [[P]]) 253; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) 254; IS__CGSCC_OPM-NEXT: br label [[TMP6]] 255; IS__CGSCC_OPM: 6: 256; IS__CGSCC_OPM-NEXT: ret void 257; 258 %2 = tail call noalias i8* @malloc(i64 4) 259 %3 = icmp eq i32 %0, 0 260 br i1 %3, label %5, label %4 261 2624: ; preds = %1 263 tail call void @nofree_func(i8* %2) 264 br label %6 265 2665: ; preds = %1 267 tail call void @nofree_arg_only(i8* %2, i8* %p) 268 tail call void @free(i8* %2) 269 br label %6 270 2716: ; preds = %5, %4 272 ret void 273} 274 275; TEST 6 - all exit paths have a call to free 276 277define void @test6(i32) { 278; IS________OPM-LABEL: define {{[^@]+}}@test6 279; IS________OPM-SAME: (i32 [[TMP0:%.*]]) 280; IS________OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) 281; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 282; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 283; IS________OPM: 4: 284; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP2]]) 285; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) 286; IS________OPM-NEXT: br label [[TMP6:%.*]] 287; IS________OPM: 5: 288; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) 289; IS________OPM-NEXT: br label [[TMP6]] 290; IS________OPM: 6: 291; IS________OPM-NEXT: ret void 292; 293; IS________NPM-LABEL: define {{[^@]+}}@test6 294; IS________NPM-SAME: (i32 [[TMP0:%.*]]) 295; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4 296; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 297; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 298; IS________NPM: 4: 299; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) 300; IS________NPM-NEXT: br label [[TMP6:%.*]] 301; IS________NPM: 5: 302; IS________NPM-NEXT: br label [[TMP6]] 303; IS________NPM: 6: 304; IS________NPM-NEXT: ret void 305; 306 %2 = tail call noalias i8* @malloc(i64 4) 307 %3 = icmp eq i32 %0, 0 308 br i1 %3, label %5, label %4 309 3104: ; preds = %1 311 tail call void @nofree_func(i8* %2) 312 tail call void @free(i8* %2) 313 br label %6 314 3155: ; preds = %1 316 tail call void @free(i8* %2) 317 br label %6 318 3196: ; preds = %5, %4 320 ret void 321} 322 323; TEST 7 - free is dead. 324 325define void @test7() { 326; IS________OPM-LABEL: define {{[^@]+}}@test7() 327; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 328; IS________OPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() 329; IS________OPM-NEXT: unreachable 330; 331; IS________NPM-LABEL: define {{[^@]+}}@test7() 332; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 333; IS________NPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() 334; IS________NPM-NEXT: unreachable 335; 336 %1 = tail call noalias i8* @malloc(i64 4) 337 tail call i32 @no_return_call() 338 tail call void @free(i8* %1) 339 ret void 340} 341 342; TEST 8 - Negative: bitcast pointer used in capture function 343 344define void @test8() { 345; CHECK-LABEL: define {{[^@]+}}@test8() 346; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 347; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 348; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 349; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 350; CHECK-NEXT: tail call void @foo(i32* align 4 [[TMP2]]) 351; CHECK-NEXT: tail call void @free(i8* nonnull align 4 dereferenceable(4) [[TMP1]]) 352; CHECK-NEXT: ret void 353; 354 %1 = tail call noalias i8* @malloc(i64 4) 355 tail call void @no_sync_func(i8* %1) 356 %2 = bitcast i8* %1 to i32* 357 store i32 10, i32* %2 358 %3 = load i32, i32* %2 359 tail call void @foo(i32* %2) 360 tail call void @free(i8* %1) 361 ret void 362} 363 364; TEST 9 - FIXME: malloc should be converted. 365define void @test9() { 366; CHECK-LABEL: define {{[^@]+}}@test9() 367; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 368; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 369; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 370; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 371; CHECK-NEXT: tail call void @foo_nounw(i32* nofree align 4 [[TMP2]]) 372; CHECK-NEXT: tail call void @free(i8* nonnull align 4 dereferenceable(4) [[TMP1]]) 373; CHECK-NEXT: ret void 374; 375 %1 = tail call noalias i8* @malloc(i64 4) 376 tail call void @no_sync_func(i8* %1) 377 %2 = bitcast i8* %1 to i32* 378 store i32 10, i32* %2 379 %3 = load i32, i32* %2 380 tail call void @foo_nounw(i32* %2) 381 tail call void @free(i8* %1) 382 ret void 383} 384 385; TEST 10 - 1 malloc, 1 free 386 387define i32 @test10() { 388; IS________OPM-LABEL: define {{[^@]+}}@test10() 389; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 390; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 391; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 392; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 393; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 394; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 395; IS________OPM-NEXT: ret i32 [[TMP3]] 396; 397; IS________NPM-LABEL: define {{[^@]+}}@test10() 398; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 399; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 400; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 401; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 402; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 403; IS________NPM-NEXT: ret i32 [[TMP3]] 404; 405 %1 = tail call noalias i8* @malloc(i64 4) 406 tail call void @no_sync_func(i8* %1) 407 %2 = bitcast i8* %1 to i32* 408 store i32 10, i32* %2 409 %3 = load i32, i32* %2 410 tail call void @free(i8* %1) 411 ret i32 %3 412} 413 414define i32 @test_lifetime() { 415; IS________OPM-LABEL: define {{[^@]+}}@test_lifetime() 416; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 417; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 418; IS________OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 419; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 420; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 421; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 422; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 423; IS________OPM-NEXT: ret i32 [[TMP3]] 424; 425; IS________NPM-LABEL: define {{[^@]+}}@test_lifetime() 426; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 427; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 428; IS________NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 429; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 430; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 431; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 432; IS________NPM-NEXT: ret i32 [[TMP3]] 433; 434 %1 = tail call noalias i8* @malloc(i64 4) 435 tail call void @no_sync_func(i8* %1) 436 call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) 437 %2 = bitcast i8* %1 to i32* 438 store i32 10, i32* %2 439 %3 = load i32, i32* %2 440 tail call void @free(i8* %1) 441 ret i32 %3 442} 443 444; TEST 11 445 446define void @test11() { 447; IS________OPM-LABEL: define {{[^@]+}}@test11() 448; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 449; IS________OPM-NEXT: tail call void @sync_will_return(i8* [[TMP1]]) 450; IS________OPM-NEXT: tail call void @free(i8* [[TMP1]]) 451; IS________OPM-NEXT: ret void 452; 453; IS________NPM-LABEL: define {{[^@]+}}@test11() 454; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 455; IS________NPM-NEXT: tail call void @sync_will_return(i8* [[TMP1]]) 456; IS________NPM-NEXT: ret void 457; 458 %1 = tail call noalias i8* @malloc(i64 4) 459 tail call void @sync_will_return(i8* %1) 460 tail call void @free(i8* %1) 461 ret void 462} 463 464; TEST 12 465define i32 @irreducible_cfg(i32 %0) { 466; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg 467; IS________OPM-SAME: (i32 [[TMP0:%.*]]) 468; IS________OPM-NEXT: [[TMP2:%.*]] = call noalias i8* @malloc(i64 4) 469; IS________OPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* 470; IS________OPM-NEXT: store i32 10, i32* [[TMP3]], align 4 471; IS________OPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 472; IS________OPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] 473; IS________OPM: 5: 474; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 475; IS________OPM-NEXT: br label [[TMP13:%.*]] 476; IS________OPM: 7: 477; IS________OPM-NEXT: br label [[TMP8:%.*]] 478; IS________OPM: 8: 479; IS________OPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] 480; IS________OPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 481; IS________OPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 482; IS________OPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 483; IS________OPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 484; IS________OPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] 485; IS________OPM: 12: 486; IS________OPM-NEXT: br label [[TMP13]] 487; IS________OPM: 13: 488; IS________OPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] 489; IS________OPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 490; IS________OPM-NEXT: br label [[TMP8]] 491; IS________OPM: 15: 492; IS________OPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* 493; IS________OPM-NEXT: call void @free(i8* [[TMP16]]) 494; IS________OPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 495; IS________OPM-NEXT: ret i32 [[TMP17]] 496; 497; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg 498; IS________NPM-SAME: (i32 [[TMP0:%.*]]) 499; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4 500; IS________NPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* 501; IS________NPM-NEXT: store i32 10, i32* [[TMP3]], align 4 502; IS________NPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 503; IS________NPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] 504; IS________NPM: 5: 505; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 506; IS________NPM-NEXT: br label [[TMP13:%.*]] 507; IS________NPM: 7: 508; IS________NPM-NEXT: br label [[TMP8:%.*]] 509; IS________NPM: 8: 510; IS________NPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] 511; IS________NPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 512; IS________NPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 513; IS________NPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 514; IS________NPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 515; IS________NPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] 516; IS________NPM: 12: 517; IS________NPM-NEXT: br label [[TMP13]] 518; IS________NPM: 13: 519; IS________NPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] 520; IS________NPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 521; IS________NPM-NEXT: br label [[TMP8]] 522; IS________NPM: 15: 523; IS________NPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* 524; IS________NPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 525; IS________NPM-NEXT: ret i32 [[TMP17]] 526; 527 %2 = call noalias i8* @malloc(i64 4) 528 %3 = bitcast i8* %2 to i32* 529 store i32 10, i32* %3, align 4 530 %4 = icmp eq i32 %0, 1 531 br i1 %4, label %5, label %7 532 5335: ; preds = %1 534 %6 = add nsw i32 %0, 5 535 br label %13 536 5377: ; preds = %1 538 br label %8 539 5408: ; preds = %13, %7 541 %.0 = phi i32 [ %14, %13 ], [ 1, %7 ] 542 %9 = load i32, i32* %3, align 4 543 %10 = add nsw i32 %9, -1 544 store i32 %10, i32* %3, align 4 545 %11 = icmp ne i32 %9, 0 546 br i1 %11, label %12, label %15 547 54812: ; preds = %8 549 br label %13 550 55113: ; preds = %12, %5 552 %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ] 553 %14 = add nsw i32 %.1, 1 554 br label %8 555 55615: ; preds = %8 557 %16 = load i32, i32* %3, align 4 558 %17 = bitcast i32* %3 to i8* 559 call void @free(i8* %17) 560 %18 = load i32, i32* %3, align 4 561 ret i32 %18 562} 563 564 565define i32 @malloc_in_loop(i32 %0) { 566; IS________OPM-LABEL: define {{[^@]+}}@malloc_in_loop 567; IS________OPM-SAME: (i32 [[TMP0:%.*]]) 568; IS________OPM-NEXT: [[TMP2:%.*]] = alloca i32, align 4 569; IS________OPM-NEXT: [[TMP3:%.*]] = alloca i32*, align 8 570; IS________OPM-NEXT: store i32 [[TMP0]], i32* [[TMP2]], align 4 571; IS________OPM-NEXT: br label [[TMP4:%.*]] 572; IS________OPM: 4: 573; IS________OPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4 574; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1 575; IS________OPM-NEXT: store i32 [[TMP6]], i32* [[TMP2]], align 4 576; IS________OPM-NEXT: [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0 577; IS________OPM-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]] 578; IS________OPM: 8: 579; IS________OPM-NEXT: [[TMP9:%.*]] = call noalias i8* @malloc(i64 4) 580; IS________OPM-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* 581; IS________OPM-NEXT: store i32 1, i32* [[TMP10]], align 8 582; IS________OPM-NEXT: br label [[TMP4]] 583; IS________OPM: 11: 584; IS________OPM-NEXT: ret i32 5 585; 586; IS________NPM-LABEL: define {{[^@]+}}@malloc_in_loop 587; IS________NPM-SAME: (i32 [[TMP0:%.*]]) 588; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i32, align 4 589; IS________NPM-NEXT: [[TMP3:%.*]] = alloca i32*, align 8 590; IS________NPM-NEXT: store i32 [[TMP0]], i32* [[TMP2]], align 4 591; IS________NPM-NEXT: br label [[TMP4:%.*]] 592; IS________NPM: 4: 593; IS________NPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4 594; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1 595; IS________NPM-NEXT: store i32 [[TMP6]], i32* [[TMP2]], align 4 596; IS________NPM-NEXT: [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0 597; IS________NPM-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]] 598; IS________NPM: 8: 599; IS________NPM-NEXT: [[TMP9:%.*]] = alloca i8, i64 4 600; IS________NPM-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* 601; IS________NPM-NEXT: store i32 1, i32* [[TMP10]], align 8 602; IS________NPM-NEXT: br label [[TMP4]] 603; IS________NPM: 11: 604; IS________NPM-NEXT: ret i32 5 605; 606 %2 = alloca i32, align 4 607 %3 = alloca i32*, align 8 608 store i32 %0, i32* %2, align 4 609 br label %4 610 6114: ; preds = %8, %1 612 %5 = load i32, i32* %2, align 4 613 %6 = add nsw i32 %5, -1 614 store i32 %6, i32* %2, align 4 615 %7 = icmp sgt i32 %6, 0 616 br i1 %7, label %8, label %11 617 6188: ; preds = %4 619 %9 = call noalias i8* @malloc(i64 4) 620 %10 = bitcast i8* %9 to i32* 621 store i32 1, i32* %10, align 8 622 br label %4 623 62411: ; preds = %4 625 ret i32 5 626} 627 628; Malloc/Calloc too large 629define i32 @test13() { 630; CHECK-LABEL: define {{[^@]+}}@test13() 631; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 256) 632; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 633; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 634; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 635; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 636; CHECK-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 637; CHECK-NEXT: ret i32 [[TMP3]] 638; 639 %1 = tail call noalias i8* @malloc(i64 256) 640 tail call void @no_sync_func(i8* %1) 641 %2 = bitcast i8* %1 to i32* 642 store i32 10, i32* %2 643 %3 = load i32, i32* %2 644 tail call void @free(i8* %1) 645 ret i32 %3 646} 647 648define i32 @test_sle() { 649; CHECK-LABEL: define {{[^@]+}}@test_sle() 650; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 -1) 651; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 652; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 653; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 654; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 655; CHECK-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 656; CHECK-NEXT: ret i32 [[TMP3]] 657; 658 %1 = tail call noalias i8* @malloc(i64 -1) 659 tail call void @no_sync_func(i8* %1) 660 %2 = bitcast i8* %1 to i32* 661 store i32 10, i32* %2 662 %3 = load i32, i32* %2 663 tail call void @free(i8* %1) 664 ret i32 %3 665} 666 667define i32 @test_overflow() { 668; CHECK-LABEL: define {{[^@]+}}@test_overflow() 669; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 65537, i64 65537) 670; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 671; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 672; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 673; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 674; CHECK-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) 675; CHECK-NEXT: ret i32 [[TMP3]] 676; 677 %1 = tail call noalias i8* @calloc(i64 65537, i64 65537) 678 tail call void @no_sync_func(i8* %1) 679 %2 = bitcast i8* %1 to i32* 680 store i32 10, i32* %2 681 %3 = load i32, i32* %2 682 tail call void @free(i8* %1) 683 ret i32 %3 684} 685 686define void @test14() { 687; CHECK-LABEL: define {{[^@]+}}@test14() 688; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 64, i64 4) 689; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 690; CHECK-NEXT: tail call void @free(i8* noalias [[TMP1]]) 691; CHECK-NEXT: ret void 692; 693 %1 = tail call noalias i8* @calloc(i64 64, i64 4) 694 tail call void @no_sync_func(i8* %1) 695 tail call void @free(i8* %1) 696 ret void 697} 698 699define void @test15(i64 %S) { 700; CHECK-LABEL: define {{[^@]+}}@test15 701; CHECK-SAME: (i64 [[S:%.*]]) 702; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]]) 703; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) 704; CHECK-NEXT: tail call void @free(i8* noalias [[TMP1]]) 705; CHECK-NEXT: ret void 706; 707 %1 = tail call noalias i8* @malloc(i64 %S) 708 tail call void @no_sync_func(i8* %1) 709 tail call void @free(i8* %1) 710 ret void 711} 712 713define void @test16a(i8 %v, i8** %P) { 714; IS________OPM-LABEL: define {{[^@]+}}@test16a 715; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) 716; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 717; IS________OPM-NEXT: store i8 [[V]], i8* [[TMP1]] 718; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree nonnull dereferenceable(1) [[TMP1]]) 719; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull dereferenceable(1) [[TMP1]]) 720; IS________OPM-NEXT: ret void 721; 722; IS________NPM-LABEL: define {{[^@]+}}@test16a 723; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) 724; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 725; IS________NPM-NEXT: store i8 [[V]], i8* [[TMP1]] 726; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree nonnull dereferenceable(1) [[TMP1]]) 727; IS________NPM-NEXT: ret void 728; 729 %1 = tail call noalias i8* @malloc(i64 4) 730 store i8 %v, i8* %1 731 tail call void @no_sync_func(i8* %1) 732 tail call void @free(i8* nonnull dereferenceable(1) %1) 733 ret void 734} 735 736define void @test16b(i8 %v, i8** %P) { 737; IS________OPM-LABEL: define {{[^@]+}}@test16b 738; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) 739; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 740; IS________OPM-NEXT: store i8* [[TMP1]], i8** [[P]] 741; IS________OPM-NEXT: tail call void @no_sync_func(i8* nofree [[TMP1]]) 742; IS________OPM-NEXT: tail call void @free(i8* [[TMP1]]) 743; IS________OPM-NEXT: ret void 744; 745; IS________NPM-LABEL: define {{[^@]+}}@test16b 746; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) 747; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 748; IS________NPM-NEXT: store i8* [[TMP1]], i8** [[P]] 749; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) 750; IS________NPM-NEXT: tail call void @free(i8* [[TMP1]]) 751; IS________NPM-NEXT: ret void 752; 753 %1 = tail call noalias i8* @malloc(i64 4) 754 store i8* %1, i8** %P 755 tail call void @no_sync_func(i8* %1) 756 tail call void @free(i8* %1) 757 ret void 758} 759 760define void @test16c(i8 %v, i8** %P) { 761; IS________OPM-LABEL: define {{[^@]+}}@test16c 762; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) 763; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 764; IS________OPM-NEXT: store i8* [[TMP1]], i8** [[P]] 765; IS________OPM-NEXT: tail call void @no_sync_func(i8* nofree [[TMP1]]) 766; IS________OPM-NEXT: tail call void @free(i8* [[TMP1]]) 767; IS________OPM-NEXT: ret void 768; 769; IS________NPM-LABEL: define {{[^@]+}}@test16c 770; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) 771; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 772; IS________NPM-NEXT: store i8* [[TMP1]], i8** [[P]] 773; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) 774; IS________NPM-NEXT: ret void 775; 776 %1 = tail call noalias i8* @malloc(i64 4) 777 store i8* %1, i8** %P 778 tail call void @no_sync_func(i8* %1) nounwind 779 tail call void @free(i8* %1) 780 ret void 781} 782 783define void @test16d(i8 %v, i8** %P) { 784; CHECK-LABEL: define {{[^@]+}}@test16d 785; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) 786; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) 787; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]] 788; CHECK-NEXT: ret void 789; 790 %1 = tail call noalias i8* @malloc(i64 4) 791 store i8* %1, i8** %P 792 ret void 793} 794