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 7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 8 9; Test cases specifically designed for the "undefined behavior" abstract function attribute. 10; We want to verify that whenever undefined behavior is assumed, the code becomes unreachable. 11; We use FIXME's to indicate problems and missing attributes. 12 13; -- Load tests -- 14 15define void @load_wholly_unreachable() { 16; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 17; CHECK-LABEL: define {{[^@]+}}@load_wholly_unreachable 18; CHECK-SAME: () #[[ATTR0:[0-9]+]] { 19; CHECK-NEXT: unreachable 20; 21 %a = load i32, i32* null 22 ret void 23} 24 25define void @loads_wholly_unreachable() { 26; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 27; CHECK-LABEL: define {{[^@]+}}@loads_wholly_unreachable 28; CHECK-SAME: () #[[ATTR0]] { 29; CHECK-NEXT: unreachable 30; 31 %a = load i32, i32* null 32 %b = load i32, i32* null 33 ret void 34} 35 36 37define void @load_single_bb_unreachable(i1 %cond) { 38; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 39; CHECK-LABEL: define {{[^@]+}}@load_single_bb_unreachable 40; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] { 41; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] 42; CHECK: t: 43; CHECK-NEXT: unreachable 44; CHECK: e: 45; CHECK-NEXT: ret void 46; 47 br i1 %cond, label %t, label %e 48t: 49 %b = load i32, i32* null 50 br label %e 51e: 52 ret void 53} 54 55; Note that while the load is removed (because it's unused), the block 56; is not changed to unreachable 57define void @load_null_pointer_is_defined() null_pointer_is_valid { 58; CHECK: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn 59; CHECK-LABEL: define {{[^@]+}}@load_null_pointer_is_defined 60; CHECK-SAME: () #[[ATTR1:[0-9]+]] { 61; CHECK-NEXT: ret void 62; 63 %a = load i32, i32* null 64 ret void 65} 66 67define internal i32* @ret_null() { 68; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 69; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_null 70; IS__CGSCC____-SAME: () #[[ATTR0]] { 71; IS__CGSCC____-NEXT: ret i32* null 72; 73 ret i32* null 74} 75 76define void @load_null_propagated() { 77; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 78; CHECK-LABEL: define {{[^@]+}}@load_null_propagated 79; CHECK-SAME: () #[[ATTR0]] { 80; CHECK-NEXT: unreachable 81; 82 %ptr = call i32* @ret_null() 83 %a = load i32, i32* %ptr 84 ret void 85} 86 87; -- Store tests -- 88 89define void @store_wholly_unreachable() { 90; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 91; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable 92; CHECK-SAME: () #[[ATTR0]] { 93; CHECK-NEXT: unreachable 94; 95 store i32 5, i32* null 96 ret void 97} 98 99define void @store_wholly_unreachable_volatile() { 100; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 101; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable_volatile 102; CHECK-SAME: () #[[ATTR2:[0-9]+]] { 103; CHECK-NEXT: store volatile i32 5, i32* null, align 4294967296 104; CHECK-NEXT: ret void 105; 106 store volatile i32 5, i32* null 107 ret void 108} 109 110define void @store_single_bb_unreachable(i1 %cond) { 111; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 112; CHECK-LABEL: define {{[^@]+}}@store_single_bb_unreachable 113; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] { 114; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] 115; CHECK: t: 116; CHECK-NEXT: unreachable 117; CHECK: e: 118; CHECK-NEXT: ret void 119; 120 br i1 %cond, label %t, label %e 121t: 122 store i32 5, i32* null 123 br label %e 124e: 125 ret void 126} 127 128define void @store_null_pointer_is_defined() null_pointer_is_valid { 129; CHECK: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly 130; CHECK-LABEL: define {{[^@]+}}@store_null_pointer_is_defined 131; CHECK-SAME: () #[[ATTR3:[0-9]+]] { 132; CHECK-NEXT: store i32 5, i32* null, align 4294967296 133; CHECK-NEXT: ret void 134; 135 store i32 5, i32* null 136 ret void 137} 138 139define void @store_null_propagated() { 140; ATTRIBUTOR-LABEL: @store_null_propagated( 141; ATTRIBUTOR-NEXT: unreachable 142; 143; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 144; CHECK-LABEL: define {{[^@]+}}@store_null_propagated 145; CHECK-SAME: () #[[ATTR0]] { 146; CHECK-NEXT: unreachable 147; 148 %ptr = call i32* @ret_null() 149 store i32 5, i32* %ptr 150 ret void 151} 152 153; -- AtomicRMW tests -- 154 155define void @atomicrmw_wholly_unreachable() { 156; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 157; CHECK-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable 158; CHECK-SAME: () #[[ATTR2]] { 159; CHECK-NEXT: unreachable 160; 161 %a = atomicrmw add i32* null, i32 1 acquire 162 ret void 163} 164 165define void @atomicrmw_single_bb_unreachable(i1 %cond) { 166; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 167; CHECK-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable 168; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR2]] { 169; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] 170; CHECK: t: 171; CHECK-NEXT: unreachable 172; CHECK: e: 173; CHECK-NEXT: ret void 174; 175 br i1 %cond, label %t, label %e 176t: 177 %a = atomicrmw add i32* null, i32 1 acquire 178 br label %e 179e: 180 ret void 181} 182 183define void @atomicrmw_null_pointer_is_defined() null_pointer_is_valid { 184; CHECK: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn 185; CHECK-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined 186; CHECK-SAME: () #[[ATTR4:[0-9]+]] { 187; CHECK-NEXT: [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire, align 4 188; CHECK-NEXT: ret void 189; 190 %a = atomicrmw add i32* null, i32 1 acquire 191 ret void 192} 193 194define void @atomicrmw_null_propagated() { 195; ATTRIBUTOR-LABEL: @atomicrmw_null_propagated( 196; ATTRIBUTOR-NEXT: unreachable 197; 198; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 199; CHECK-LABEL: define {{[^@]+}}@atomicrmw_null_propagated 200; CHECK-SAME: () #[[ATTR2]] { 201; CHECK-NEXT: unreachable 202; 203 %ptr = call i32* @ret_null() 204 %a = atomicrmw add i32* %ptr, i32 1 acquire 205 ret void 206} 207 208; -- AtomicCmpXchg tests -- 209 210define void @atomiccmpxchg_wholly_unreachable() { 211; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 212; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable 213; CHECK-SAME: () #[[ATTR2]] { 214; CHECK-NEXT: unreachable 215; 216 %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic 217 ret void 218} 219 220define void @atomiccmpxchg_single_bb_unreachable(i1 %cond) { 221; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 222; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable 223; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR2]] { 224; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] 225; CHECK: t: 226; CHECK-NEXT: unreachable 227; CHECK: e: 228; CHECK-NEXT: ret void 229; 230 br i1 %cond, label %t, label %e 231t: 232 %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic 233 br label %e 234e: 235 ret void 236} 237 238define void @atomiccmpxchg_null_pointer_is_defined() null_pointer_is_valid { 239; CHECK: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn 240; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined 241; CHECK-SAME: () #[[ATTR4]] { 242; CHECK-NEXT: [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic, align 4 243; CHECK-NEXT: ret void 244; 245 %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic 246 ret void 247} 248 249define void @atomiccmpxchg_null_propagated() { 250; ATTRIBUTOR-LABEL: @atomiccmpxchg_null_propagated( 251; ATTRIBUTOR-NEXT: unreachable 252; 253; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn 254; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated 255; CHECK-SAME: () #[[ATTR2]] { 256; CHECK-NEXT: unreachable 257; 258 %ptr = call i32* @ret_null() 259 %a = cmpxchg i32* %ptr, i32 2, i32 3 acq_rel monotonic 260 ret void 261} 262 263; -- Conditional branching tests -- 264 265; Note: The unreachable on %t and %e is _not_ from AAUndefinedBehavior 266 267define i32 @cond_br_on_undef() { 268; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn 269; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef 270; CHECK-SAME: () #[[ATTR5:[0-9]+]] { 271; CHECK-NEXT: unreachable 272; CHECK: t: 273; CHECK-NEXT: unreachable 274; CHECK: e: 275; CHECK-NEXT: unreachable 276; 277 br i1 undef, label %t, label %e 278t: 279 ret i32 1 280e: 281 ret i32 2 282} 283 284; More complicated branching 285 ; Valid branch - verify that this is not converted 286 ; to unreachable. 287define void @cond_br_on_undef2(i1 %cond) { 288; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 289; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef2 290; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] { 291; CHECK-NEXT: br i1 [[COND]], label [[T1:%.*]], label [[E1:%.*]] 292; CHECK: t1: 293; CHECK-NEXT: unreachable 294; CHECK: t2: 295; CHECK-NEXT: unreachable 296; CHECK: e2: 297; CHECK-NEXT: unreachable 298; CHECK: e1: 299; CHECK-NEXT: ret void 300; 301 br i1 %cond, label %t1, label %e1 302t1: 303 br i1 undef, label %t2, label %e2 304t2: 305 ret void 306e2: 307 ret void 308e1: 309 ret void 310} 311 312define i1 @ret_undef() { 313; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 314; CHECK-LABEL: define {{[^@]+}}@ret_undef 315; CHECK-SAME: () #[[ATTR0]] { 316; CHECK-NEXT: ret i1 undef 317; 318 ret i1 undef 319} 320 321define void @cond_br_on_undef_interproc() { 322; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn 323; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc 324; CHECK-SAME: () #[[ATTR5]] { 325; CHECK-NEXT: unreachable 326; CHECK: t: 327; CHECK-NEXT: unreachable 328; CHECK: e: 329; CHECK-NEXT: unreachable 330; 331 %cond = call i1 @ret_undef() 332 br i1 %cond, label %t, label %e 333t: 334 ret void 335e: 336 ret void 337} 338 339define i1 @ret_undef2() { 340; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 341; CHECK-LABEL: define {{[^@]+}}@ret_undef2 342; CHECK-SAME: () #[[ATTR0]] { 343; CHECK-NEXT: br i1 true, label [[T:%.*]], label [[E:%.*]] 344; CHECK: t: 345; CHECK-NEXT: ret i1 undef 346; CHECK: e: 347; CHECK-NEXT: unreachable 348; 349 br i1 true, label %t, label %e 350t: 351 ret i1 undef 352e: 353 ret i1 undef 354} 355 356; More complicated interproc deduction of undef 357define void @cond_br_on_undef_interproc2() { 358; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn 359; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2 360; CHECK-SAME: () #[[ATTR5]] { 361; CHECK-NEXT: unreachable 362; CHECK: t: 363; CHECK-NEXT: unreachable 364; CHECK: e: 365; CHECK-NEXT: unreachable 366; 367 %cond = call i1 @ret_undef2() 368 br i1 %cond, label %t, label %e 369t: 370 ret void 371e: 372 ret void 373} 374 375; Branch on undef that depends on propagation of 376; undef of a previous instruction. 377define i32 @cond_br_on_undef3() { 378; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 379; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef3 380; CHECK-SAME: () #[[ATTR0]] { 381; CHECK-NEXT: br label [[T:%.*]] 382; CHECK: t: 383; CHECK-NEXT: ret i32 1 384; CHECK: e: 385; CHECK-NEXT: unreachable 386; 387 %cond = icmp ne i32 1, undef 388 br i1 %cond, label %t, label %e 389t: 390 ret i32 1 391e: 392 ret i32 2 393} 394 395; Branch on undef because of uninitialized value. 396; FIXME: Currently it doesn't propagate the undef. 397define i32 @cond_br_on_undef_uninit() { 398; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn 399; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit 400; CHECK-SAME: () #[[ATTR5]] { 401; CHECK-NEXT: unreachable 402; CHECK: t: 403; CHECK-NEXT: unreachable 404; CHECK: e: 405; CHECK-NEXT: unreachable 406; 407 %alloc = alloca i1 408 %cond = load i1, i1* %alloc 409 br i1 %cond, label %t, label %e 410t: 411 ret i32 1 412e: 413 ret i32 2 414} 415 416; Note that the `load` has UB (so it will be changed to unreachable) 417; and the branch is a terminator that can be constant-folded. 418; We want to test that doing both won't cause a segfault. 419; MODULE-NOT: @callee( 420define internal i32 @callee(i1 %C, i32* %A) { 421; 422; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 423; IS__CGSCC____-LABEL: define {{[^@]+}}@callee 424; IS__CGSCC____-SAME: () #[[ATTR0]] { 425; IS__CGSCC____-NEXT: entry: 426; IS__CGSCC____-NEXT: unreachable 427; IS__CGSCC____: T: 428; IS__CGSCC____-NEXT: unreachable 429; IS__CGSCC____: F: 430; IS__CGSCC____-NEXT: ret i32 1 431; 432entry: 433 %A.0 = load i32, i32* null 434 br i1 %C, label %T, label %F 435 436T: 437 ret i32 %A.0 438 439F: 440 ret i32 1 441} 442 443define i32 @foo() { 444; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 445; CHECK-LABEL: define {{[^@]+}}@foo 446; CHECK-SAME: () #[[ATTR0]] { 447; CHECK-NEXT: ret i32 1 448; 449 %X = call i32 @callee(i1 false, i32* null) 450 ret i32 %X 451} 452 453; Tests for nonnull noundef attribute violation. 454; 455; Tests for argument position 456 457define void @arg_nonnull_1(i32* nonnull %a) { 458; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 459; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_1 460; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] { 461; CHECK-NEXT: store i32 0, i32* [[A]], align 4 462; CHECK-NEXT: ret void 463; 464 store i32 0, i32* %a 465 ret void 466} 467 468define void @arg_nonnull_1_noundef_1(i32* nonnull noundef %a) { 469; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 470; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1 471; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6]] { 472; CHECK-NEXT: store i32 0, i32* [[A]], align 4 473; CHECK-NEXT: ret void 474; 475 store i32 0, i32* %a 476 ret void 477} 478 479define void @arg_nonnull_12(i32* nonnull %a, i32* nonnull %b, i32* %c) { 480; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 481; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_12 482; CHECK-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR6]] { 483; CHECK-NEXT: [[D:%.*]] = icmp eq i32* [[C]], null 484; CHECK-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]] 485; CHECK: t: 486; CHECK-NEXT: store i32 0, i32* [[A]], align 4 487; CHECK-NEXT: br label [[RET:%.*]] 488; CHECK: f: 489; CHECK-NEXT: store i32 1, i32* [[B]], align 4 490; CHECK-NEXT: br label [[RET]] 491; CHECK: ret: 492; CHECK-NEXT: ret void 493; 494 %d = icmp eq i32* %c, null 495 br i1 %d, label %t, label %f 496t: 497 store i32 0, i32* %a 498 br label %ret 499f: 500 store i32 1, i32* %b 501 br label %ret 502ret: 503 ret void 504} 505 506define void @arg_nonnull_12_noundef_2(i32* nonnull %a, i32* noundef nonnull %b, i32* %c) { 507; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 508; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2 509; CHECK-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree noundef nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR6]] { 510; CHECK-NEXT: [[D:%.*]] = icmp eq i32* [[C]], null 511; CHECK-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]] 512; CHECK: t: 513; CHECK-NEXT: store i32 0, i32* [[A]], align 4 514; CHECK-NEXT: br label [[RET:%.*]] 515; CHECK: f: 516; CHECK-NEXT: store i32 1, i32* [[B]], align 4 517; CHECK-NEXT: br label [[RET]] 518; CHECK: ret: 519; CHECK-NEXT: ret void 520; 521 %d = icmp eq i32* %c, null 522 br i1 %d, label %t, label %f 523t: 524 store i32 0, i32* %a 525 br label %ret 526f: 527 store i32 1, i32* %b 528 br label %ret 529ret: 530 ret void 531} 532 533; Pass null directly to argument with nonnull attribute 534define void @arg_nonnull_violation1_1() { 535; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 536; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation1_1 537; CHECK-SAME: () #[[ATTR0]] { 538; CHECK-NEXT: unreachable 539; 540 call void @arg_nonnull_1(i32* null) 541 ret void 542} 543 544define void @arg_nonnull_violation1_2() { 545; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 546; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation1_2 547; CHECK-SAME: () #[[ATTR0]] { 548; CHECK-NEXT: unreachable 549; 550 call void @arg_nonnull_1_noundef_1(i32* null) 551 ret void 552} 553 554; A case that depends on value simplification 555define void @arg_nonnull_violation2_1(i1 %c) { 556; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 557; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation2_1 558; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 559; CHECK-NEXT: unreachable 560; 561 %null = getelementptr i32, i32* null, i32 0 562 %mustnull = select i1 %c, i32* null, i32* %null 563 call void @arg_nonnull_1(i32* %mustnull) 564 ret void 565} 566 567define void @arg_nonnull_violation2_2(i1 %c) { 568; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 569; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation2_2 570; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 571; CHECK-NEXT: unreachable 572; 573 %null = getelementptr i32, i32* null, i32 0 574 %mustnull = select i1 %c, i32* null, i32* %null 575 call void @arg_nonnull_1_noundef_1(i32* %mustnull) 576 ret void 577} 578 579; Cases for single and multiple violation at a callsite 580define void @arg_nonnull_violation3_1(i1 %c) { 581; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 582; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1 583; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 584; IS__TUNIT____-NEXT: [[PTR:%.*]] = alloca i32, align 4 585; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 586; IS__TUNIT____: t: 587; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7:[0-9]+]] 588; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR7]] 589; IS__TUNIT____-NEXT: unreachable 590; IS__TUNIT____: f: 591; IS__TUNIT____-NEXT: unreachable 592; IS__TUNIT____: ret: 593; IS__TUNIT____-NEXT: ret void 594; 595; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 596; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1 597; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 598; IS__CGSCC____-NEXT: [[PTR:%.*]] = alloca i32, align 4 599; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 600; IS__CGSCC____: t: 601; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR8:[0-9]+]] 602; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR8]] 603; IS__CGSCC____-NEXT: unreachable 604; IS__CGSCC____: f: 605; IS__CGSCC____-NEXT: unreachable 606; IS__CGSCC____: ret: 607; IS__CGSCC____-NEXT: ret void 608; 609 %ptr = alloca i32 610 br i1 %c, label %t, label %f 611t: 612 call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* %ptr) 613 call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* null) 614 call void @arg_nonnull_12(i32* %ptr, i32* null, i32* %ptr) 615 call void @arg_nonnull_12(i32* %ptr, i32* null, i32* null) 616 br label %ret 617f: 618 call void @arg_nonnull_12(i32* null, i32* %ptr, i32* %ptr) 619 call void @arg_nonnull_12(i32* null, i32* %ptr, i32* null) 620 call void @arg_nonnull_12(i32* null, i32* null, i32* %ptr) 621 call void @arg_nonnull_12(i32* null, i32* null, i32* null) 622 br label %ret 623ret: 624 ret void 625} 626 627define void @arg_nonnull_violation3_2(i1 %c) { 628; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 629; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2 630; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 631; IS__TUNIT____-NEXT: [[PTR:%.*]] = alloca i32, align 4 632; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 633; IS__TUNIT____: t: 634; IS__TUNIT____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7]] 635; IS__TUNIT____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR7]] 636; IS__TUNIT____-NEXT: unreachable 637; IS__TUNIT____: f: 638; IS__TUNIT____-NEXT: unreachable 639; IS__TUNIT____: ret: 640; IS__TUNIT____-NEXT: ret void 641; 642; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 643; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2 644; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 645; IS__CGSCC____-NEXT: [[PTR:%.*]] = alloca i32, align 4 646; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 647; IS__CGSCC____: t: 648; IS__CGSCC____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR8]] 649; IS__CGSCC____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR8]] 650; IS__CGSCC____-NEXT: unreachable 651; IS__CGSCC____: f: 652; IS__CGSCC____-NEXT: unreachable 653; IS__CGSCC____: ret: 654; IS__CGSCC____-NEXT: ret void 655; 656 %ptr = alloca i32 657 br i1 %c, label %t, label %f 658t: 659 call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* %ptr) 660 call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* null) 661 call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* %ptr) 662 call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* null) 663 br label %ret 664f: 665 call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* %ptr) 666 call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* null) 667 call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* %ptr) 668 call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* null) 669 br label %ret 670ret: 671 ret void 672} 673 674; Tests for returned position 675 676define nonnull i32* @returned_nonnnull(i32 %c) { 677; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 678; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull 679; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 680; CHECK-NEXT: switch i32 [[C]], label [[ONDEFAULT:%.*]] [ 681; CHECK-NEXT: i32 0, label [[ONZERO:%.*]] 682; CHECK-NEXT: i32 1, label [[ONONE:%.*]] 683; CHECK-NEXT: ] 684; CHECK: onzero: 685; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 4 686; CHECK-NEXT: ret i32* [[PTR]] 687; CHECK: onone: 688; CHECK-NEXT: ret i32* null 689; CHECK: ondefault: 690; CHECK-NEXT: ret i32* undef 691; 692 switch i32 %c, label %ondefault [ i32 0, label %onzero 693 i32 1, label %onone ] 694onzero: 695 %ptr = alloca i32 696 ret i32* %ptr 697onone: 698 ret i32* null 699ondefault: 700 ret i32* undef 701} 702 703define noundef i32* @returned_noundef(i32 %c) { 704; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 705; CHECK-LABEL: define {{[^@]+}}@returned_noundef 706; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 707; CHECK-NEXT: switch i32 [[C]], label [[ONDEFAULT:%.*]] [ 708; CHECK-NEXT: i32 0, label [[ONZERO:%.*]] 709; CHECK-NEXT: i32 1, label [[ONONE:%.*]] 710; CHECK-NEXT: ] 711; CHECK: onzero: 712; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 4 713; CHECK-NEXT: ret i32* [[PTR]] 714; CHECK: onone: 715; CHECK-NEXT: ret i32* null 716; CHECK: ondefault: 717; CHECK-NEXT: unreachable 718; 719 switch i32 %c, label %ondefault [ i32 0, label %onzero 720 i32 1, label %onone ] 721onzero: 722 %ptr = alloca i32 723 ret i32* %ptr 724onone: 725 ret i32* null 726ondefault: 727 ret i32* undef 728} 729 730define nonnull noundef i32* @returned_nonnnull_noundef(i32 %c) { 731; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 732; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull_noundef 733; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { 734; CHECK-NEXT: switch i32 [[C]], label [[ONDEFAULT:%.*]] [ 735; CHECK-NEXT: i32 0, label [[ONZERO:%.*]] 736; CHECK-NEXT: i32 1, label [[ONONE:%.*]] 737; CHECK-NEXT: ] 738; CHECK: onzero: 739; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 4 740; CHECK-NEXT: ret i32* [[PTR]] 741; CHECK: onone: 742; CHECK-NEXT: unreachable 743; CHECK: ondefault: 744; CHECK-NEXT: unreachable 745; 746 switch i32 %c, label %ondefault [ i32 0, label %onzero 747 i32 1, label %onone ] 748onzero: 749 %ptr = alloca i32 750 ret i32* %ptr 751onone: 752 ret i32* null 753ondefault: 754 ret i32* undef 755} 756 757define noundef i32 @returned_nonnnull_noundef_int() { 758; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 759; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull_noundef_int 760; CHECK-SAME: () #[[ATTR0]] { 761; CHECK-NEXT: ret i32 0 762; 763 ret i32 0 764} 765 766declare void @callee_int_arg(i32) 767 768define void @callsite_noundef_1() { 769; CHECK-LABEL: define {{[^@]+}}@callsite_noundef_1() { 770; CHECK-NEXT: call void @callee_int_arg(i32 noundef 0) 771; CHECK-NEXT: ret void 772; 773 call void @callee_int_arg(i32 noundef 0) 774 ret void 775} 776 777declare void @callee_ptr_arg(i32*) 778 779define void @callsite_noundef_2() { 780; CHECK-LABEL: define {{[^@]+}}@callsite_noundef_2() { 781; CHECK-NEXT: unreachable 782; 783 call void @callee_ptr_arg(i32* noundef undef) 784 ret void 785} 786 787define i32 @argument_noundef1(i32 noundef %c) { 788; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 789; CHECK-LABEL: define {{[^@]+}}@argument_noundef1 790; CHECK-SAME: (i32 noundef returned [[C:%.*]]) #[[ATTR0]] { 791; CHECK-NEXT: ret i32 [[C]] 792; 793 ret i32 %c 794} 795 796define i32 @violate_noundef_nonpointer() { 797; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 798; CHECK-LABEL: define {{[^@]+}}@violate_noundef_nonpointer 799; CHECK-SAME: () #[[ATTR0]] { 800; CHECK-NEXT: ret i32 undef 801; 802 %ret = call i32 @argument_noundef1(i32 undef) 803 ret i32 %ret 804} 805 806define i32* @argument_noundef2(i32* noundef %c) { 807; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 808; CHECK-LABEL: define {{[^@]+}}@argument_noundef2 809; CHECK-SAME: (i32* nofree noundef readnone returned "no-capture-maybe-returned" [[C:%.*]]) #[[ATTR0]] { 810; CHECK-NEXT: ret i32* [[C]] 811; 812 ret i32* %c 813} 814 815define i32* @violate_noundef_pointer() { 816; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 817; CHECK-LABEL: define {{[^@]+}}@violate_noundef_pointer 818; CHECK-SAME: () #[[ATTR0]] { 819; CHECK-NEXT: ret i32* undef 820; 821 %ret = call i32* @argument_noundef2(i32* undef) 822 ret i32* %ret 823} 824 825define internal noundef i32 @assumed_undef_is_ok(i1 %c, i32 %arg) { 826; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn 827; IS__CGSCC____-LABEL: define {{[^@]+}}@assumed_undef_is_ok 828; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR7:[0-9]+]] { 829; IS__CGSCC____-NEXT: br i1 [[C]], label [[REC:%.*]], label [[RET:%.*]] 830; IS__CGSCC____: rec: 831; IS__CGSCC____-NEXT: br label [[RET]] 832; IS__CGSCC____: ret: 833; IS__CGSCC____-NEXT: ret i32 0 834; 835 %stack = alloca i32 836 store i32 %arg, i32* %stack 837 br i1 %c, label %rec, label %ret 838rec: 839 %call = call i32 @assumed_undef_is_ok(i1 false, i32 0) 840 store i32 %call, i32* %stack 841 br label %ret 842ret: 843 %l = load i32, i32* %stack 844 ret i32 %l 845} 846 847define noundef i32 @assumed_undef_is_ok_caller(i1 %c) { 848; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 849; CHECK-LABEL: define {{[^@]+}}@assumed_undef_is_ok_caller 850; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { 851; CHECK-NEXT: ret i32 0 852; 853 %call = call i32 @assumed_undef_is_ok(i1 %c, i32 undef) 854 ret i32 %call 855} 856 857;. 858; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 859; IS__TUNIT____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } 860; IS__TUNIT____: attributes #[[ATTR2]] = { nofree norecurse nounwind readnone willreturn } 861; IS__TUNIT____: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly } 862; IS__TUNIT____: attributes #[[ATTR4]] = { nofree norecurse nounwind null_pointer_is_valid willreturn } 863; IS__TUNIT____: attributes #[[ATTR5]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } 864; IS__TUNIT____: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } 865; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nosync nounwind willreturn writeonly } 866;. 867; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } 868; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } 869; IS__CGSCC____: attributes #[[ATTR2]] = { nofree norecurse nounwind readnone willreturn } 870; IS__CGSCC____: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly } 871; IS__CGSCC____: attributes #[[ATTR4]] = { nofree norecurse nounwind null_pointer_is_valid willreturn } 872; IS__CGSCC____: attributes #[[ATTR5]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } 873; IS__CGSCC____: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } 874; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone willreturn } 875; IS__CGSCC____: attributes #[[ATTR8]] = { nounwind willreturn writeonly } 876;. 877