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