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