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