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:o-i64:64-f80:128-n8:16:32:64-S128" 6 7declare ptr @geti1Ptr() 8 9; Make sure we do *not* return true. 10;. 11; CHECK: @G1 = private global ptr undef 12; CHECK: @G2 = private global ptr undef 13; CHECK: @G3 = private global i1 undef 14;. 15define internal i1 @recursive_inst_comparator(ptr %a, ptr %b) { 16; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 17; CHECK-LABEL: define {{[^@]+}}@recursive_inst_comparator 18; CHECK-SAME: (ptr noalias nofree readnone [[A:%.*]], ptr noalias nofree readnone [[B:%.*]]) #[[ATTR0:[0-9]+]] { 19; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[B]] 20; CHECK-NEXT: ret i1 [[CMP]] 21; 22 %cmp = icmp eq ptr %a, %b 23 ret i1 %cmp 24} 25 26define internal i1 @recursive_inst_generator(i1 %c, ptr %p) { 27; TUNIT-LABEL: define {{[^@]+}}@recursive_inst_generator 28; TUNIT-SAME: (i1 [[C:%.*]], ptr nofree [[P:%.*]]) { 29; TUNIT-NEXT: [[A:%.*]] = call ptr @geti1Ptr() 30; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 31; TUNIT: t: 32; TUNIT-NEXT: [[R1:%.*]] = call i1 @recursive_inst_comparator(ptr noalias nofree readnone [[A]], ptr noalias nofree readnone [[P]]) #[[ATTR7:[0-9]+]] 33; TUNIT-NEXT: ret i1 [[R1]] 34; TUNIT: f: 35; TUNIT-NEXT: [[R2:%.*]] = call i1 @recursive_inst_generator(i1 noundef true, ptr nofree [[A]]) 36; TUNIT-NEXT: ret i1 [[R2]] 37; 38; CGSCC-LABEL: define {{[^@]+}}@recursive_inst_generator 39; CGSCC-SAME: (i1 [[C:%.*]], ptr nofree [[P:%.*]]) { 40; CGSCC-NEXT: [[A:%.*]] = call ptr @geti1Ptr() 41; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 42; CGSCC: t: 43; CGSCC-NEXT: [[R1:%.*]] = call i1 @recursive_inst_comparator(ptr noalias nofree readnone [[A]], ptr noalias nofree readnone [[P]]) 44; CGSCC-NEXT: ret i1 [[R1]] 45; CGSCC: f: 46; CGSCC-NEXT: [[R2:%.*]] = call i1 @recursive_inst_generator(i1 noundef true, ptr nofree [[A]]) 47; CGSCC-NEXT: ret i1 [[R2]] 48; 49 %a = call ptr @geti1Ptr() 50 br i1 %c, label %t, label %f 51t: 52 %r1 = call i1 @recursive_inst_comparator(ptr %a, ptr %p) 53 ret i1 %r1 54f: 55 %r2 = call i1 @recursive_inst_generator(i1 true, ptr %a) 56 ret i1 %r2 57} 58 59; FIXME: This should *not* return true. 60define i1 @recursive_inst_generator_caller(i1 %c) { 61; TUNIT-LABEL: define {{[^@]+}}@recursive_inst_generator_caller 62; TUNIT-SAME: (i1 [[C:%.*]]) { 63; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_generator(i1 [[C]], ptr undef) 64; TUNIT-NEXT: ret i1 [[CALL]] 65; 66; CGSCC-LABEL: define {{[^@]+}}@recursive_inst_generator_caller 67; CGSCC-SAME: (i1 [[C:%.*]]) { 68; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_generator(i1 [[C]], ptr nofree undef) 69; CGSCC-NEXT: ret i1 [[CALL]] 70; 71 %call = call i1 @recursive_inst_generator(i1 %c, ptr undef) 72 ret i1 %call 73} 74 75; Make sure we do *not* return true. 76define internal i1 @recursive_inst_compare(i1 %c, ptr %p) { 77; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare 78; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) { 79; CHECK-NEXT: [[A:%.*]] = call ptr @geti1Ptr() 80; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 81; CHECK: t: 82; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[P]] 83; CHECK-NEXT: ret i1 [[CMP]] 84; CHECK: f: 85; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare(i1 noundef true, ptr [[A]]) 86; CHECK-NEXT: ret i1 [[CALL]] 87; 88 %a = call ptr @geti1Ptr() 89 br i1 %c, label %t, label %f 90t: 91 %cmp = icmp eq ptr %a, %p 92 ret i1 %cmp 93f: 94 %call = call i1 @recursive_inst_compare(i1 true, ptr %a) 95 ret i1 %call 96} 97 98; FIXME: This should *not* return true. 99define i1 @recursive_inst_compare_caller(i1 %c) { 100; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare_caller 101; CHECK-SAME: (i1 [[C:%.*]]) { 102; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare(i1 [[C]], ptr undef) 103; CHECK-NEXT: ret i1 [[CALL]] 104; 105 %call = call i1 @recursive_inst_compare(i1 %c, ptr undef) 106 ret i1 %call 107} 108 109; Make sure we do *not* return true. 110define internal i1 @recursive_alloca_compare(i1 %c, ptr %p) { 111; CHECK: Function Attrs: nofree nosync nounwind memory(none) 112; CHECK-LABEL: define {{[^@]+}}@recursive_alloca_compare 113; CHECK-SAME: (i1 noundef [[C:%.*]], ptr noalias nofree readnone [[P:%.*]]) #[[ATTR1:[0-9]+]] { 114; CHECK-NEXT: [[A:%.*]] = alloca i1, align 1 115; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 116; CHECK: t: 117; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[P]] 118; CHECK-NEXT: ret i1 [[CMP]] 119; CHECK: f: 120; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 noundef true, ptr noalias nofree noundef nonnull readnone dereferenceable(1) [[A]]) #[[ATTR1]] 121; CHECK-NEXT: ret i1 [[CALL]] 122; 123 %a = alloca i1 124 br i1 %c, label %t, label %f 125t: 126 %cmp = icmp eq ptr %a, %p 127 ret i1 %cmp 128f: 129 %call = call i1 @recursive_alloca_compare(i1 true, ptr %a) 130 ret i1 %call 131} 132 133; FIXME: This should *not* return true. 134define i1 @recursive_alloca_compare_caller(i1 %c) { 135; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none) 136; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller 137; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] { 138; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 noundef [[C]], ptr undef) #[[ATTR1]] 139; TUNIT-NEXT: ret i1 [[CALL]] 140; 141; CGSCC: Function Attrs: nofree nosync nounwind memory(none) 142; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller 143; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] { 144; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 noundef [[C]], ptr nofree undef) #[[ATTR1]] 145; CGSCC-NEXT: ret i1 [[CALL]] 146; 147 %call = call i1 @recursive_alloca_compare(i1 %c, ptr undef) 148 ret i1 %call 149} 150 151; Make sure we do *not* simplify this to return 0 or 1, return 42 is ok though. 152define internal i8 @recursive_alloca_load_return(i1 %c, ptr %p, i8 %v) { 153; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: readwrite) 154; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_load_return 155; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr noalias nofree readonly captures(none) [[P:%.*]], i8 noundef [[V:%.*]]) #[[ATTR3:[0-9]+]] { 156; TUNIT-NEXT: [[A:%.*]] = alloca i8, align 1 157; TUNIT-NEXT: store i8 [[V]], ptr [[A]], align 1 158; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 159; TUNIT: t: 160; TUNIT-NEXT: store i8 0, ptr [[A]], align 1 161; TUNIT-NEXT: [[L:%.*]] = load i8, ptr [[P]], align 1 162; TUNIT-NEXT: ret i8 [[L]] 163; TUNIT: f: 164; TUNIT-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 noundef true, ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[A]], i8 noundef 1) #[[ATTR4:[0-9]+]] 165; TUNIT-NEXT: ret i8 [[CALL]] 166; 167; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite) 168; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_load_return 169; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr noalias nofree readonly captures(none) [[P:%.*]], i8 noundef [[V:%.*]]) #[[ATTR2:[0-9]+]] { 170; CGSCC-NEXT: [[A:%.*]] = alloca i8, align 1 171; CGSCC-NEXT: store i8 [[V]], ptr [[A]], align 1 172; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 173; CGSCC: t: 174; CGSCC-NEXT: store i8 0, ptr [[A]], align 1 175; CGSCC-NEXT: [[L:%.*]] = load i8, ptr [[P]], align 1 176; CGSCC-NEXT: ret i8 [[L]] 177; CGSCC: f: 178; CGSCC-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 noundef true, ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[A]], i8 noundef 1) #[[ATTR3:[0-9]+]] 179; CGSCC-NEXT: ret i8 [[CALL]] 180; 181 %a = alloca i8 182 store i8 %v, ptr %a 183 br i1 %c, label %t, label %f 184t: 185 store i8 0, ptr %a 186 %l = load i8, ptr %p 187 ret i8 %l 188f: 189 %call = call i8 @recursive_alloca_load_return(i1 true, ptr %a, i8 1) 190 ret i8 %call 191} 192 193define i8 @recursive_alloca_load_return_caller(i1 %c) { 194; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none) 195; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_load_return_caller 196; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR2]] { 197; TUNIT-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 noundef [[C]], ptr undef, i8 noundef 42) #[[ATTR4]] 198; TUNIT-NEXT: ret i8 [[CALL]] 199; 200; CGSCC: Function Attrs: nofree nosync nounwind memory(none) 201; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_load_return_caller 202; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] { 203; CGSCC-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 noundef [[C]], ptr nofree undef, i8 noundef 42) #[[ATTR5:[0-9]+]] 204; CGSCC-NEXT: ret i8 [[CALL]] 205; 206 %call = call i8 @recursive_alloca_load_return(i1 %c, ptr undef, i8 42) 207 ret i8 %call 208} 209 210@G1 = private global ptr undef 211@G2 = private global ptr undef 212@G3 = private global i1 undef 213 214; Make sure we do *not* return true. 215define internal i1 @recursive_alloca_compare_global1(i1 %c) { 216; TUNIT: Function Attrs: nofree nosync nounwind 217; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_compare_global1 218; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR4]] { 219; TUNIT-NEXT: [[A:%.*]] = alloca i1, align 1 220; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 221; TUNIT: t: 222; TUNIT-NEXT: [[P:%.*]] = load ptr, ptr @G1, align 8 223; TUNIT-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[P]] 224; TUNIT-NEXT: ret i1 [[CMP]] 225; TUNIT: f: 226; TUNIT-NEXT: store ptr [[A]], ptr @G1, align 8 227; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef true) #[[ATTR4]] 228; TUNIT-NEXT: ret i1 [[CALL]] 229; 230; CGSCC: Function Attrs: nofree nosync nounwind 231; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_compare_global1 232; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] { 233; CGSCC-NEXT: [[A:%.*]] = alloca i1, align 1 234; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 235; CGSCC: t: 236; CGSCC-NEXT: [[P:%.*]] = load ptr, ptr @G1, align 8 237; CGSCC-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[P]] 238; CGSCC-NEXT: ret i1 [[CMP]] 239; CGSCC: f: 240; CGSCC-NEXT: store ptr [[A]], ptr @G1, align 8 241; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef true) #[[ATTR3]] 242; CGSCC-NEXT: ret i1 [[CALL]] 243; 244 %a = alloca i1 245 br i1 %c, label %t, label %f 246t: 247 %p = load ptr, ptr @G1 248 %cmp = icmp eq ptr %a, %p 249 ret i1 %cmp 250f: 251 store ptr %a, ptr @G1 252 %call = call i1 @recursive_alloca_compare_global1(i1 true) 253 ret i1 %call 254} 255 256; FIXME: This should *not* return true. 257define i1 @recursive_alloca_compare_caller_global1(i1 %c) { 258; TUNIT: Function Attrs: nofree norecurse nosync nounwind 259; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global1 260; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR5:[0-9]+]] { 261; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef [[C]]) #[[ATTR4]] 262; TUNIT-NEXT: ret i1 [[CALL]] 263; 264; CGSCC: Function Attrs: nofree nosync nounwind 265; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global1 266; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] { 267; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef [[C]]) #[[ATTR5]] 268; CGSCC-NEXT: ret i1 [[CALL]] 269; 270 %call = call i1 @recursive_alloca_compare_global1(i1 %c) 271 ret i1 %call 272} 273 274define internal i1 @recursive_alloca_compare_global2(i1 %c) { 275; TUNIT: Function Attrs: nofree nosync nounwind 276; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_compare_global2 277; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR4]] { 278; TUNIT-NEXT: [[A:%.*]] = alloca i1, align 1 279; TUNIT-NEXT: [[P:%.*]] = load ptr, ptr @G2, align 8 280; TUNIT-NEXT: store ptr [[A]], ptr @G2, align 8 281; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 282; TUNIT: t: 283; TUNIT-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[P]] 284; TUNIT-NEXT: ret i1 [[CMP]] 285; TUNIT: f: 286; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef true) #[[ATTR4]] 287; TUNIT-NEXT: ret i1 [[CALL]] 288; 289; CGSCC: Function Attrs: nofree nosync nounwind 290; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_compare_global2 291; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] { 292; CGSCC-NEXT: [[A:%.*]] = alloca i1, align 1 293; CGSCC-NEXT: [[P:%.*]] = load ptr, ptr @G2, align 8 294; CGSCC-NEXT: store ptr [[A]], ptr @G2, align 8 295; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 296; CGSCC: t: 297; CGSCC-NEXT: [[CMP:%.*]] = icmp eq ptr [[A]], [[P]] 298; CGSCC-NEXT: ret i1 [[CMP]] 299; CGSCC: f: 300; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef true) #[[ATTR3]] 301; CGSCC-NEXT: ret i1 [[CALL]] 302; 303 %a = alloca i1 304 %p = load ptr, ptr @G2 305 store ptr %a, ptr @G2 306 br i1 %c, label %t, label %f 307t: 308 %cmp = icmp eq ptr %a, %p 309 ret i1 %cmp 310f: 311 %call = call i1 @recursive_alloca_compare_global2(i1 true) 312 ret i1 %call 313} 314 315; FIXME: This should *not* return true. 316define i1 @recursive_alloca_compare_caller_global2(i1 %c) { 317; TUNIT: Function Attrs: nofree norecurse nosync nounwind 318; TUNIT-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global2 319; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR5]] { 320; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef [[C]]) #[[ATTR4]] 321; TUNIT-NEXT: ret i1 [[CALL]] 322; 323; CGSCC: Function Attrs: nofree nosync nounwind 324; CGSCC-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global2 325; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] { 326; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef [[C]]) #[[ATTR5]] 327; CGSCC-NEXT: ret i1 [[CALL]] 328; 329 %call = call i1 @recursive_alloca_compare_global2(i1 %c) 330 ret i1 %call 331} 332define internal i1 @recursive_inst_compare_global3(i1 %c) { 333; 334; TUNIT: Function Attrs: nofree nosync nounwind 335; TUNIT-LABEL: define {{[^@]+}}@recursive_inst_compare_global3 336; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR4]] { 337; TUNIT-NEXT: [[P:%.*]] = load i1, ptr @G3, align 1 338; TUNIT-NEXT: store i1 [[C]], ptr @G3, align 1 339; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 340; TUNIT: t: 341; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i1 [[C]], [[P]] 342; TUNIT-NEXT: ret i1 [[CMP]] 343; TUNIT: f: 344; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef true) #[[ATTR4]] 345; TUNIT-NEXT: ret i1 [[CALL]] 346; 347; CGSCC: Function Attrs: nofree nosync nounwind 348; CGSCC-LABEL: define {{[^@]+}}@recursive_inst_compare_global3 349; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] { 350; CGSCC-NEXT: [[P:%.*]] = load i1, ptr @G3, align 1 351; CGSCC-NEXT: store i1 [[C]], ptr @G3, align 1 352; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] 353; CGSCC: t: 354; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i1 [[C]], [[P]] 355; CGSCC-NEXT: ret i1 [[CMP]] 356; CGSCC: f: 357; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef true) #[[ATTR3]] 358; CGSCC-NEXT: ret i1 [[CALL]] 359; 360 %p = load i1, ptr @G3 361 store i1 %c, ptr @G3 362 br i1 %c, label %t, label %f 363t: 364 %cmp = icmp eq i1 %c, %p 365 ret i1 %cmp 366f: 367 %call = call i1 @recursive_inst_compare_global3(i1 true) 368 ret i1 %call 369} 370 371; FIXME: This should *not* return true. 372define i1 @recursive_inst_compare_caller_global3(i1 %c) { 373; TUNIT: Function Attrs: nofree norecurse nosync nounwind 374; TUNIT-LABEL: define {{[^@]+}}@recursive_inst_compare_caller_global3 375; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR5]] { 376; TUNIT-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef [[C]]) #[[ATTR4]] 377; TUNIT-NEXT: ret i1 [[CALL]] 378; 379; CGSCC: Function Attrs: nofree nosync nounwind 380; CGSCC-LABEL: define {{[^@]+}}@recursive_inst_compare_caller_global3 381; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] { 382; CGSCC-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef [[C]]) #[[ATTR5]] 383; CGSCC-NEXT: ret i1 [[CALL]] 384; 385 %call = call i1 @recursive_inst_compare_global3(i1 %c) 386 ret i1 %call 387} 388 389define i32 @non_unique_phi_ops(ptr %ptr) { 390; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 391; TUNIT-LABEL: define {{[^@]+}}@non_unique_phi_ops 392; TUNIT-SAME: (ptr nofree readonly captures(none) [[PTR:%.*]]) #[[ATTR6:[0-9]+]] { 393; TUNIT-NEXT: entry: 394; TUNIT-NEXT: br label [[HEADER:%.*]] 395; TUNIT: header: 396; TUNIT-NEXT: [[I:%.*]] = phi i32 [ [[ADD:%.*]], [[F:%.*]] ], [ 0, [[ENTRY:%.*]] ] 397; TUNIT-NEXT: [[P:%.*]] = phi i32 [ [[NON_UNIQUE:%.*]], [[F]] ], [ poison, [[ENTRY]] ] 398; TUNIT-NEXT: [[ADD]] = add i32 [[I]], 1 399; TUNIT-NEXT: [[G:%.*]] = getelementptr i32, ptr [[PTR]], i32 [[I]] 400; TUNIT-NEXT: [[NON_UNIQUE_INPUT:%.*]] = load i32, ptr [[G]], align 4 401; TUNIT-NEXT: [[CMP1:%.*]] = icmp eq i32 [[I]], [[NON_UNIQUE_INPUT]] 402; TUNIT-NEXT: br i1 [[CMP1]], label [[T:%.*]], label [[F]] 403; TUNIT: t: 404; TUNIT-NEXT: br label [[F]] 405; TUNIT: f: 406; TUNIT-NEXT: [[NON_UNIQUE]] = phi i32 [ [[NON_UNIQUE_INPUT]], [[T]] ], [ [[P]], [[HEADER]] ] 407; TUNIT-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 42 408; TUNIT-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[END:%.*]] 409; TUNIT: end: 410; TUNIT-NEXT: ret i32 [[P]] 411; 412; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) 413; CGSCC-LABEL: define {{[^@]+}}@non_unique_phi_ops 414; CGSCC-SAME: (ptr nofree readonly captures(none) [[PTR:%.*]]) #[[ATTR4:[0-9]+]] { 415; CGSCC-NEXT: entry: 416; CGSCC-NEXT: br label [[HEADER:%.*]] 417; CGSCC: header: 418; CGSCC-NEXT: [[I:%.*]] = phi i32 [ [[ADD:%.*]], [[F:%.*]] ], [ 0, [[ENTRY:%.*]] ] 419; CGSCC-NEXT: [[P:%.*]] = phi i32 [ [[NON_UNIQUE:%.*]], [[F]] ], [ poison, [[ENTRY]] ] 420; CGSCC-NEXT: [[ADD]] = add i32 [[I]], 1 421; CGSCC-NEXT: [[G:%.*]] = getelementptr i32, ptr [[PTR]], i32 [[I]] 422; CGSCC-NEXT: [[NON_UNIQUE_INPUT:%.*]] = load i32, ptr [[G]], align 4 423; CGSCC-NEXT: [[CMP1:%.*]] = icmp eq i32 [[I]], [[NON_UNIQUE_INPUT]] 424; CGSCC-NEXT: br i1 [[CMP1]], label [[T:%.*]], label [[F]] 425; CGSCC: t: 426; CGSCC-NEXT: br label [[F]] 427; CGSCC: f: 428; CGSCC-NEXT: [[NON_UNIQUE]] = phi i32 [ [[NON_UNIQUE_INPUT]], [[T]] ], [ [[P]], [[HEADER]] ] 429; CGSCC-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 42 430; CGSCC-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[END:%.*]] 431; CGSCC: end: 432; CGSCC-NEXT: ret i32 [[P]] 433; 434entry: 435 br label %header 436 437header: 438 %i = phi i32 [ %add, %f ], [ 0, %entry ] 439 %p = phi i32 [ %non_unique, %f ], [ poison, %entry ] 440 %add = add i32 %i, 1 441 %g = getelementptr i32, ptr %ptr, i32 %i 442 %non_unique_input = load i32, ptr %g, align 4 443 %cmp1 = icmp eq i32 %i, %non_unique_input 444 br i1 %cmp1, label %t, label %f 445t: 446 br label %f 447f: 448 %non_unique = phi i32 [ %non_unique_input, %t ], [ %p, %header ] 449 %cmp2 = icmp slt i32 %i, 42 450 br i1 %cmp2, label %header, label %end 451 452end: 453 ret i32 %p 454} 455 456;. 457; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 458; TUNIT: attributes #[[ATTR1]] = { nofree nosync nounwind memory(none) } 459; TUNIT: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind memory(none) } 460; TUNIT: attributes #[[ATTR3]] = { nofree nosync nounwind memory(argmem: readwrite) } 461; TUNIT: attributes #[[ATTR4]] = { nofree nosync nounwind } 462; TUNIT: attributes #[[ATTR5]] = { nofree norecurse nosync nounwind } 463; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } 464; TUNIT: attributes #[[ATTR7]] = { nounwind memory(none) } 465;. 466; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 467; CGSCC: attributes #[[ATTR1]] = { nofree nosync nounwind memory(none) } 468; CGSCC: attributes #[[ATTR2]] = { nofree nosync nounwind memory(argmem: readwrite) } 469; CGSCC: attributes #[[ATTR3]] = { nofree nosync nounwind } 470; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } 471; CGSCC: attributes #[[ATTR5]] = { nofree nounwind } 472;. 473