1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -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=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM 6 7target triple = "amdgcn-amd-amdhsa" 8 9declare noalias i8* @malloc(i64) 10 11declare void @nocapture_func_frees_pointer(i8* nocapture) 12 13declare void @func_throws(...) 14 15declare void @sync_func(i8* %p) 16 17declare void @sync_will_return(i8* %p) willreturn nounwind 18 19declare void @no_sync_func(i8* nocapture %p) nofree nosync willreturn 20 21declare void @nofree_func(i8* nocapture %p) nofree nosync willreturn 22 23declare void @foo(i32* %p) 24 25declare void @foo_nounw(i32* %p) nounwind nofree 26 27declare i32 @no_return_call() noreturn 28 29declare void @free(i8* nocapture) 30 31declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind 32 33define void @nofree_arg_only(i8* %p1, i8* %p2) { 34; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only 35; CHECK-SAME: (i8* nocapture nofree [[P1:%.*]], i8* nocapture [[P2:%.*]]) { 36; CHECK-NEXT: tail call void @free(i8* nocapture [[P2]]) 37; CHECK-NEXT: tail call void @nofree_func(i8* nocapture nofree [[P1]]) 38; CHECK-NEXT: ret void 39; 40 tail call void @free(i8* %p2) 41 tail call void @nofree_func(i8* %p1) 42 ret void 43} 44 45; TEST 1 - negative, pointer freed in another function. 46 47define void @test1() { 48; CHECK-LABEL: define {{[^@]+}}@test1() { 49; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 50; CHECK-NEXT: tail call void @nocapture_func_frees_pointer(i8* noalias nocapture [[TMP1]]) 51; CHECK-NEXT: tail call void (...) @func_throws() 52; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 53; CHECK-NEXT: ret void 54; 55 %1 = tail call noalias i8* @malloc(i64 4) 56 tail call void @nocapture_func_frees_pointer(i8* %1) 57 tail call void (...) @func_throws() 58 tail call void @free(i8* %1) 59 ret void 60} 61 62; TEST 2 - negative, call to a sync function. 63 64define void @test2() { 65; CHECK-LABEL: define {{[^@]+}}@test2() { 66; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 67; CHECK-NEXT: tail call void @sync_func(i8* [[TMP1]]) 68; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP1]]) 69; CHECK-NEXT: ret void 70; 71 %1 = tail call noalias i8* @malloc(i64 4) 72 tail call void @sync_func(i8* %1) 73 tail call void @free(i8* %1) 74 ret void 75} 76 77; TEST 3 - 1 malloc, 1 free 78 79define void @test3() { 80; CHECK-LABEL: define {{[^@]+}}@test3() { 81; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 82; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 83; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 84; CHECK-NEXT: ret void 85; 86 %1 = tail call noalias i8* @malloc(i64 4) 87 tail call void @no_sync_func(i8* %1) 88 tail call void @free(i8* %1) 89 ret void 90} 91 92define void @test3a(i8* %p) { 93; IS________OPM-LABEL: define {{[^@]+}}@test3a 94; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) { 95; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 96; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) 97; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 98; IS________OPM-NEXT: ret void 99; 100; IS________NPM-LABEL: define {{[^@]+}}@test3a 101; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) { 102; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 103; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) 104; IS________NPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 105; IS________NPM-NEXT: ret void 106; 107 %1 = tail call noalias i8* @malloc(i64 4) 108 tail call void @nofree_arg_only(i8* %1, i8* %p) 109 tail call void @free(i8* %1) 110 ret void 111} 112 113declare noalias i8* @aligned_alloc(i64, i64) 114 115define void @test3b(i8* %p) { 116; IS________OPM-LABEL: define {{[^@]+}}@test3b 117; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) { 118; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128) 119; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) 120; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 121; IS________OPM-NEXT: ret void 122; 123; IS________NPM-LABEL: define {{[^@]+}}@test3b 124; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) { 125; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128) 126; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) 127; IS________NPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 128; IS________NPM-NEXT: ret void 129; 130 %1 = tail call noalias i8* @aligned_alloc(i64 32, i64 128) 131 tail call void @nofree_arg_only(i8* %1, i8* %p) 132 tail call void @free(i8* %1) 133 ret void 134} 135 136; leave alone non-constant alignments. 137define void @test3c(i64 %alignment) { 138; CHECK-LABEL: define {{[^@]+}}@test3c 139; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) { 140; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128) 141; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 142; CHECK-NEXT: ret void 143; 144 %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128) 145 tail call void @free(i8* %1) 146 ret void 147} 148 149declare noalias i8* @calloc(i64, i64) 150 151define void @test0() { 152; CHECK-LABEL: define {{[^@]+}}@test0() { 153; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 2, i64 noundef 4) 154; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 155; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 156; CHECK-NEXT: ret void 157; 158 %1 = tail call noalias i8* @calloc(i64 2, i64 4) 159 tail call void @no_sync_func(i8* %1) 160 tail call void @free(i8* %1) 161 ret void 162} 163 164; TEST 4 165define void @test4() { 166; CHECK-LABEL: define {{[^@]+}}@test4() { 167; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 168; CHECK-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP1]]) 169; CHECK-NEXT: ret void 170; 171 %1 = tail call noalias i8* @malloc(i64 4) 172 tail call void @nofree_func(i8* %1) 173 ret void 174} 175 176; TEST 5 - not all exit paths have a call to free, but all uses of malloc 177; are in nofree functions and are not captured 178 179define void @test5(i32, i8* %p) { 180; IS________OPM-LABEL: define {{[^@]+}}@test5 181; IS________OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) { 182; IS________OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 183; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 184; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 185; IS________OPM: 4: 186; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) 187; IS________OPM-NEXT: br label [[TMP6:%.*]] 188; IS________OPM: 5: 189; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]]) 190; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) 191; IS________OPM-NEXT: br label [[TMP6]] 192; IS________OPM: 6: 193; IS________OPM-NEXT: ret void 194; 195; IS________NPM-LABEL: define {{[^@]+}}@test5 196; IS________NPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) { 197; IS________NPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 198; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 199; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 200; IS________NPM: 4: 201; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) 202; IS________NPM-NEXT: br label [[TMP6:%.*]] 203; IS________NPM: 5: 204; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP2]], i8* nocapture [[P]]) 205; IS________NPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) 206; IS________NPM-NEXT: br label [[TMP6]] 207; IS________NPM: 6: 208; IS________NPM-NEXT: ret void 209; 210 %2 = tail call noalias i8* @malloc(i64 4) 211 %3 = icmp eq i32 %0, 0 212 br i1 %3, label %5, label %4 213 2144: ; preds = %1 215 tail call void @nofree_func(i8* %2) 216 br label %6 217 2185: ; preds = %1 219 tail call void @nofree_arg_only(i8* %2, i8* %p) 220 tail call void @free(i8* %2) 221 br label %6 222 2236: ; preds = %5, %4 224 ret void 225} 226 227; TEST 6 - all exit paths have a call to free 228 229define void @test6(i32) { 230; CHECK-LABEL: define {{[^@]+}}@test6 231; CHECK-SAME: (i32 [[TMP0:%.*]]) { 232; CHECK-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 233; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 234; CHECK-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] 235; CHECK: 4: 236; CHECK-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) 237; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) 238; CHECK-NEXT: br label [[TMP6:%.*]] 239; CHECK: 5: 240; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) 241; CHECK-NEXT: br label [[TMP6]] 242; CHECK: 6: 243; CHECK-NEXT: ret void 244; 245 %2 = tail call noalias i8* @malloc(i64 4) 246 %3 = icmp eq i32 %0, 0 247 br i1 %3, label %5, label %4 248 2494: ; preds = %1 250 tail call void @nofree_func(i8* %2) 251 tail call void @free(i8* %2) 252 br label %6 253 2545: ; preds = %1 255 tail call void @free(i8* %2) 256 br label %6 257 2586: ; preds = %5, %4 259 ret void 260} 261 262; TEST 7 - free is dead. 263 264define void @test7() { 265; CHECK: Function Attrs: noreturn 266; CHECK-LABEL: define {{[^@]+}}@test7 267; CHECK-SAME: () #[[ATTR3:[0-9]+]] { 268; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 269; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() #[[ATTR3]] 270; CHECK-NEXT: unreachable 271; 272 %1 = tail call noalias i8* @malloc(i64 4) 273 tail call i32 @no_return_call() 274 tail call void @free(i8* %1) 275 ret void 276} 277 278; TEST 8 - Negative: bitcast pointer used in capture function 279 280define void @test8() { 281; CHECK-LABEL: define {{[^@]+}}@test8() { 282; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 283; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 284; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 285; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 286; CHECK-NEXT: tail call void @foo(i32* noundef align 4 [[TMP2]]) 287; CHECK-NEXT: tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 288; CHECK-NEXT: ret void 289; 290 %1 = tail call noalias i8* @malloc(i64 4) 291 tail call void @no_sync_func(i8* %1) 292 %2 = bitcast i8* %1 to i32* 293 store i32 10, i32* %2 294 %3 = load i32, i32* %2 295 tail call void @foo(i32* %2) 296 tail call void @free(i8* %1) 297 ret void 298} 299 300; TEST 9 - FIXME: malloc should be converted. 301define void @test9() { 302; CHECK-LABEL: define {{[^@]+}}@test9() { 303; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 304; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 305; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 306; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 307; CHECK-NEXT: tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR5:[0-9]+]] 308; CHECK-NEXT: tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 309; CHECK-NEXT: ret void 310; 311 %1 = tail call noalias i8* @malloc(i64 4) 312 tail call void @no_sync_func(i8* %1) 313 %2 = bitcast i8* %1 to i32* 314 store i32 10, i32* %2 315 %3 = load i32, i32* %2 316 tail call void @foo_nounw(i32* %2) 317 tail call void @free(i8* %1) 318 ret void 319} 320 321; TEST 10 - 1 malloc, 1 free 322 323define i32 @test10() { 324; CHECK-LABEL: define {{[^@]+}}@test10() { 325; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 326; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 327; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 328; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 329; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 330; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 331; CHECK-NEXT: ret i32 [[TMP3]] 332; 333 %1 = tail call noalias i8* @malloc(i64 4) 334 tail call void @no_sync_func(i8* %1) 335 %2 = bitcast i8* %1 to i32* 336 store i32 10, i32* %2 337 %3 = load i32, i32* %2 338 tail call void @free(i8* %1) 339 ret i32 %3 340} 341 342define i32 @test_lifetime() { 343; CHECK-LABEL: define {{[^@]+}}@test_lifetime() { 344; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 345; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 346; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 347; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 348; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 349; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 350; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 351; CHECK-NEXT: ret i32 [[TMP3]] 352; 353 %1 = tail call noalias i8* @malloc(i64 4) 354 tail call void @no_sync_func(i8* %1) 355 call void @llvm.lifetime.start.p0i8(i64 4, 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 @free(i8* %1) 360 ret i32 %3 361} 362 363; TEST 11 364 365define void @test11() { 366; CHECK-LABEL: define {{[^@]+}}@test11() { 367; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 368; CHECK-NEXT: tail call void @sync_will_return(i8* [[TMP1]]) #[[ATTR5]] 369; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP1]]) 370; CHECK-NEXT: ret void 371; 372 %1 = tail call noalias i8* @malloc(i64 4) 373 tail call void @sync_will_return(i8* %1) 374 tail call void @free(i8* %1) 375 ret void 376} 377 378; TEST 12 379define i32 @irreducible_cfg(i32 %0) { 380; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg 381; IS________OPM-SAME: (i32 [[TMP0:%.*]]) { 382; IS________OPM-NEXT: [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4) 383; IS________OPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* 384; IS________OPM-NEXT: store i32 10, i32* [[TMP3]], align 4 385; IS________OPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 386; IS________OPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] 387; IS________OPM: 5: 388; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 389; IS________OPM-NEXT: br label [[TMP13:%.*]] 390; IS________OPM: 7: 391; IS________OPM-NEXT: br label [[TMP8:%.*]] 392; IS________OPM: 8: 393; IS________OPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] 394; IS________OPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 395; IS________OPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 396; IS________OPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 397; IS________OPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 398; IS________OPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] 399; IS________OPM: 12: 400; IS________OPM-NEXT: br label [[TMP13]] 401; IS________OPM: 13: 402; IS________OPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] 403; IS________OPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 404; IS________OPM-NEXT: br label [[TMP8]] 405; IS________OPM: 15: 406; IS________OPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4 407; IS________OPM-NEXT: [[TMP17:%.*]] = bitcast i32* [[TMP3]] to i8* 408; IS________OPM-NEXT: call void @free(i8* nocapture noundef [[TMP17]]) 409; IS________OPM-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP3]], align 4 410; IS________OPM-NEXT: ret i32 [[TMP18]] 411; 412; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg 413; IS________NPM-SAME: (i32 [[TMP0:%.*]]) { 414; IS________NPM-NEXT: [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4) 415; IS________NPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* 416; IS________NPM-NEXT: store i32 10, i32* [[TMP3]], align 4 417; IS________NPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 418; IS________NPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] 419; IS________NPM: 5: 420; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 421; IS________NPM-NEXT: br label [[TMP13:%.*]] 422; IS________NPM: 7: 423; IS________NPM-NEXT: br label [[TMP8:%.*]] 424; IS________NPM: 8: 425; IS________NPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] 426; IS________NPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 427; IS________NPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 428; IS________NPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 429; IS________NPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 430; IS________NPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] 431; IS________NPM: 12: 432; IS________NPM-NEXT: br label [[TMP13]] 433; IS________NPM: 13: 434; IS________NPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] 435; IS________NPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 436; IS________NPM-NEXT: br label [[TMP8]] 437; IS________NPM: 15: 438; IS________NPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4 439; IS________NPM-NEXT: call void @free(i8* nocapture noundef [[TMP2]]) 440; IS________NPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 441; IS________NPM-NEXT: ret i32 [[TMP17]] 442; 443 %2 = call noalias i8* @malloc(i64 4) 444 %3 = bitcast i8* %2 to i32* 445 store i32 10, i32* %3, align 4 446 %4 = icmp eq i32 %0, 1 447 br i1 %4, label %5, label %7 448 4495: ; preds = %1 450 %6 = add nsw i32 %0, 5 451 br label %13 452 4537: ; preds = %1 454 br label %8 455 4568: ; preds = %13, %7 457 %.0 = phi i32 [ %14, %13 ], [ 1, %7 ] 458 %9 = load i32, i32* %3, align 4 459 %10 = add nsw i32 %9, -1 460 store i32 %10, i32* %3, align 4 461 %11 = icmp ne i32 %9, 0 462 br i1 %11, label %12, label %15 463 46412: ; preds = %8 465 br label %13 466 46713: ; preds = %12, %5 468 %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ] 469 %14 = add nsw i32 %.1, 1 470 br label %8 471 47215: ; preds = %8 473 %16 = load i32, i32* %3, align 4 474 %17 = bitcast i32* %3 to i8* 475 call void @free(i8* %17) 476 %18 = load i32, i32* %3, align 4 477 ret i32 %18 478} 479 480 481define i32 @malloc_in_loop(i32 %0) { 482; CHECK-LABEL: define {{[^@]+}}@malloc_in_loop 483; CHECK-SAME: (i32 [[TMP0:%.*]]) { 484; CHECK-NEXT: [[TMP2:%.*]] = alloca i32, align 4 485; CHECK-NEXT: [[TMP3:%.*]] = alloca i32*, align 8 486; CHECK-NEXT: store i32 [[TMP0]], i32* [[TMP2]], align 4 487; CHECK-NEXT: br label [[TMP4:%.*]] 488; CHECK: 4: 489; CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4 490; CHECK-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1 491; CHECK-NEXT: store i32 [[TMP6]], i32* [[TMP2]], align 4 492; CHECK-NEXT: [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0 493; CHECK-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]] 494; CHECK: 8: 495; CHECK-NEXT: [[TMP9:%.*]] = call noalias i8* @malloc(i64 noundef 4) 496; CHECK-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* 497; CHECK-NEXT: br label [[TMP4]] 498; CHECK: 11: 499; CHECK-NEXT: ret i32 5 500; 501 %2 = alloca i32, align 4 502 %3 = alloca i32*, align 8 503 store i32 %0, i32* %2, align 4 504 br label %4 505 5064: ; preds = %8, %1 507 %5 = load i32, i32* %2, align 4 508 %6 = add nsw i32 %5, -1 509 store i32 %6, i32* %2, align 4 510 %7 = icmp sgt i32 %6, 0 511 br i1 %7, label %8, label %11 512 5138: ; preds = %4 514 %9 = call noalias i8* @malloc(i64 4) 515 %10 = bitcast i8* %9 to i32* 516 store i32 1, i32* %10, align 8 517 br label %4 518 51911: ; preds = %4 520 ret i32 5 521} 522 523; Malloc/Calloc too large 524define i32 @test13() { 525; CHECK-LABEL: define {{[^@]+}}@test13() { 526; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 256) 527; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 528; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 529; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 530; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 531; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 532; CHECK-NEXT: ret i32 [[TMP3]] 533; 534 %1 = tail call noalias i8* @malloc(i64 256) 535 tail call void @no_sync_func(i8* %1) 536 %2 = bitcast i8* %1 to i32* 537 store i32 10, i32* %2 538 %3 = load i32, i32* %2 539 tail call void @free(i8* %1) 540 ret i32 %3 541} 542 543define i32 @test_sle() { 544; CHECK-LABEL: define {{[^@]+}}@test_sle() { 545; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef -1) 546; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 547; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 548; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 549; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 550; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 551; CHECK-NEXT: ret i32 [[TMP3]] 552; 553 %1 = tail call noalias i8* @malloc(i64 -1) 554 tail call void @no_sync_func(i8* %1) 555 %2 = bitcast i8* %1 to i32* 556 store i32 10, i32* %2 557 %3 = load i32, i32* %2 558 tail call void @free(i8* %1) 559 ret i32 %3 560} 561 562define i32 @test_overflow() { 563; CHECK-LABEL: define {{[^@]+}}@test_overflow() { 564; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 65537, i64 noundef 65537) 565; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 566; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* 567; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 568; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 569; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) 570; CHECK-NEXT: ret i32 [[TMP3]] 571; 572 %1 = tail call noalias i8* @calloc(i64 65537, i64 65537) 573 tail call void @no_sync_func(i8* %1) 574 %2 = bitcast i8* %1 to i32* 575 store i32 10, i32* %2 576 %3 = load i32, i32* %2 577 tail call void @free(i8* %1) 578 ret i32 %3 579} 580 581define void @test14() { 582; CHECK-LABEL: define {{[^@]+}}@test14() { 583; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 64, i64 noundef 4) 584; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 585; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 586; CHECK-NEXT: ret void 587; 588 %1 = tail call noalias i8* @calloc(i64 64, i64 4) 589 tail call void @no_sync_func(i8* %1) 590 tail call void @free(i8* %1) 591 ret void 592} 593 594define void @test15(i64 %S) { 595; CHECK-LABEL: define {{[^@]+}}@test15 596; CHECK-SAME: (i64 [[S:%.*]]) { 597; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]]) 598; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) 599; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) 600; CHECK-NEXT: ret void 601; 602 %1 = tail call noalias i8* @malloc(i64 %S) 603 tail call void @no_sync_func(i8* %1) 604 tail call void @free(i8* %1) 605 ret void 606} 607 608define void @test16a(i8 %v, i8** %P) { 609; CHECK-LABEL: define {{[^@]+}}@test16a 610; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) { 611; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 612; CHECK-NEXT: store i8 [[V]], i8* [[TMP1]], align 1 613; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]]) 614; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]]) 615; CHECK-NEXT: ret void 616; 617 %1 = tail call noalias i8* @malloc(i64 4) 618 store i8 %v, i8* %1 619 tail call void @no_sync_func(i8* %1) 620 tail call void @free(i8* nonnull dereferenceable(1) %1) 621 ret void 622} 623 624define void @test16b(i8 %v, i8** %P) { 625; CHECK-LABEL: define {{[^@]+}}@test16b 626; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) { 627; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 628; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 629; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) 630; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP1]]) 631; CHECK-NEXT: ret void 632; 633 %1 = tail call noalias i8* @malloc(i64 4) 634 store i8* %1, i8** %P 635 tail call void @no_sync_func(i8* %1) 636 tail call void @free(i8* %1) 637 ret void 638} 639 640define void @test16c(i8 %v, i8** %P) { 641; CHECK-LABEL: define {{[^@]+}}@test16c 642; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) { 643; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 644; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 645; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR5]] 646; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP1]]) 647; CHECK-NEXT: ret void 648; 649 %1 = tail call noalias i8* @malloc(i64 4) 650 store i8* %1, i8** %P 651 tail call void @no_sync_func(i8* %1) nounwind 652 tail call void @free(i8* %1) 653 ret void 654} 655 656define void @test16d(i8 %v, i8** %P) { 657; CHECK-LABEL: define {{[^@]+}}@test16d 658; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) { 659; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) 660; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 661; CHECK-NEXT: ret void 662; 663 %1 = tail call noalias i8* @malloc(i64 4) 664 store i8* %1, i8** %P 665 ret void 666} 667;. 668; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn } 669; CHECK: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn } 670; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind } 671; CHECK: attributes #[[ATTR3]] = { noreturn } 672; CHECK: attributes #[[ATTR4:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn } 673; CHECK: attributes #[[ATTR5]] = { nounwind } 674;. 675