1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals 2; RUN: opt -passes=attributor -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,UPTO2,UNLIM,OUNLM 3; RUN: opt -passes=attributor -attributor-print-call-graph -S -disable-output < %s | FileCheck %s --check-prefixes=DOT 4; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=2 -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,UPTO2,LIMI2 5; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=0 -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,LIMI0 6; RUN: opt -passes=attributor --attributor-assume-closed-world -S < %s | FileCheck %s --check-prefixes=CHECK,UPTO2,UNLIM,CWRLD 7 8;. 9; CHECK: @G = global ptr @usedByGlobal 10;. 11define dso_local void @func1() { 12; CHECK-LABEL: @func1( 13; CHECK-NEXT: br label [[TMP2:%.*]] 14; CHECK: 1: 15; CHECK-NEXT: unreachable 16; CHECK: 2: 17; CHECK-NEXT: call void @func3() 18; CHECK-NEXT: ret void 19; 20 %1 = icmp ne i32 0, 0 21 br i1 %1, label %2, label %3 22 232: ; preds = %0 24 call void @func2(i1 false) 25 br label %3 26 273: ; preds = %2, %0 28 call void () @func3() 29 ret void 30} 31 32declare void @func3() 33define internal void @func4() { 34; CHECK-LABEL: @func4( 35; CHECK-NEXT: call void @func3() 36; CHECK-NEXT: ret void 37; 38 call void @func3() 39 ret void 40} 41define internal void @internal_good() { 42; CHECK-LABEL: @internal_good( 43; CHECK-NEXT: call void @void(ptr @func4) 44; CHECK-NEXT: ret void 45; 46 call void @void(ptr @func4) 47 ret void 48} 49 50define dso_local void @func2(i1 %c) { 51; UPTO2-LABEL: @func2( 52; UPTO2-NEXT: [[F:%.*]] = select i1 [[C:%.*]], ptr @internal_good, ptr @func4 53; UPTO2-NEXT: [[TMP1:%.*]] = icmp eq ptr [[F]], @func4 54; UPTO2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 55; UPTO2: 2: 56; UPTO2-NEXT: call void @func4() 57; UPTO2-NEXT: br label [[TMP6:%.*]] 58; UPTO2: 3: 59; UPTO2-NEXT: br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]] 60; UPTO2: 4: 61; UPTO2-NEXT: call void @internal_good() 62; UPTO2-NEXT: br label [[TMP6]] 63; UPTO2: 5: 64; UPTO2-NEXT: unreachable 65; UPTO2: 6: 66; UPTO2-NEXT: ret void 67; 68; LIMI0-LABEL: @func2( 69; LIMI0-NEXT: [[F:%.*]] = select i1 [[C:%.*]], ptr @internal_good, ptr @func4 70; LIMI0-NEXT: call void [[F]](), !callees [[META0:![0-9]+]] 71; LIMI0-NEXT: ret void 72; 73 %f = select i1 %c, ptr @internal_good, ptr @func4 74 call void %f() 75 ret void 76} 77 78 79define void @func5(i32 %0) { 80; UPTO2-LABEL: @func5( 81; UPTO2-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 82; UPTO2-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], ptr @func4, ptr @func3 83; UPTO2-NEXT: [[TMP4:%.*]] = icmp eq ptr [[TMP3]], @func3 84; UPTO2-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 85; UPTO2: 5: 86; UPTO2-NEXT: call void @func3() 87; UPTO2-NEXT: br label [[TMP9:%.*]] 88; UPTO2: 6: 89; UPTO2-NEXT: br i1 true, label [[TMP7:%.*]], label [[TMP8:%.*]] 90; UPTO2: 7: 91; UPTO2-NEXT: call void @func4() 92; UPTO2-NEXT: br label [[TMP9]] 93; UPTO2: 8: 94; UPTO2-NEXT: unreachable 95; UPTO2: 9: 96; UPTO2-NEXT: ret void 97; 98; LIMI0-LABEL: @func5( 99; LIMI0-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 100; LIMI0-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], ptr @func4, ptr @func3 101; LIMI0-NEXT: call void [[TMP3]](), !callees [[META1:![0-9]+]] 102; LIMI0-NEXT: ret void 103; 104 %2 = icmp ne i32 %0, 0 105 %3 = select i1 %2, ptr @func4, ptr @func3 106 call void () %3() 107 ret void 108} 109 110define i32 @musttailCall(i32 %0) { 111; CHECK-LABEL: @musttailCall( 112; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 113; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], ptr @func4, ptr @func3 114; CHECK-NEXT: [[C:%.*]] = musttail call i32 [[TMP3]](i32 0) 115; CHECK-NEXT: ret i32 [[C]] 116; 117 %2 = icmp ne i32 %0, 0 118 %3 = select i1 %2, ptr @func4, ptr @func3 119 %c = musttail call i32 (i32) %3(i32 0) 120 ret i32 %c 121} 122 123declare i32 @retI32() 124declare void @takeI32(i32) 125declare float @retFloatTakeFloat(float) 126; This callee is always filtered out because of the noundef argument 127declare float @retFloatTakeFloatFloatNoundef(float, float noundef) 128declare void @void() 129 130define i32 @non_matching_fp1(i1 %c1, i1 %c2, i1 %c) { 131; UNLIM-LABEL: @non_matching_fp1( 132; UNLIM-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 133; UNLIM-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void 134; UNLIM-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 135; UNLIM-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 136; UNLIM-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 137; UNLIM: 2: 138; UNLIM-NEXT: [[CALL1:%.*]] = call i32 @takeI32(i32 42) 139; UNLIM-NEXT: br label [[TMP15:%.*]] 140; UNLIM: 3: 141; UNLIM-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 142; UNLIM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 143; UNLIM: 5: 144; UNLIM-NEXT: [[CALL2:%.*]] = call i32 @retI32(i32 42) 145; UNLIM-NEXT: br label [[TMP15]] 146; UNLIM: 6: 147; UNLIM-NEXT: [[TMP7:%.*]] = icmp eq ptr [[FP]], @void 148; UNLIM-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]] 149; UNLIM: 8: 150; UNLIM-NEXT: [[CALL3:%.*]] = call i32 @void(i32 42) 151; UNLIM-NEXT: br label [[TMP15]] 152; UNLIM: 9: 153; UNLIM-NEXT: br i1 true, label [[TMP10:%.*]], label [[TMP14:%.*]] 154; UNLIM: 10: 155; UNLIM-NEXT: [[TMP11:%.*]] = bitcast i32 42 to float 156; UNLIM-NEXT: [[TMP12:%.*]] = call float @retFloatTakeFloat(float [[TMP11]]) 157; UNLIM-NEXT: [[TMP13:%.*]] = bitcast float [[TMP12]] to i32 158; UNLIM-NEXT: br label [[TMP15]] 159; UNLIM: 14: 160; UNLIM-NEXT: unreachable 161; UNLIM: 15: 162; UNLIM-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP8]] ], [ [[TMP13]], [[TMP10]] ] 163; UNLIM-NEXT: ret i32 [[CALL_PHI]] 164; 165; LIMI2-LABEL: @non_matching_fp1( 166; LIMI2-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 167; LIMI2-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void 168; LIMI2-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 169; LIMI2-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 170; LIMI2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 171; LIMI2: 2: 172; LIMI2-NEXT: [[CALL1:%.*]] = call i32 @takeI32(i32 42) 173; LIMI2-NEXT: br label [[TMP7:%.*]] 174; LIMI2: 3: 175; LIMI2-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 176; LIMI2-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 177; LIMI2: 5: 178; LIMI2-NEXT: [[CALL2:%.*]] = call i32 @retI32(i32 42) 179; LIMI2-NEXT: br label [[TMP7]] 180; LIMI2: 6: 181; LIMI2-NEXT: [[CALL3:%.*]] = call i32 [[FP]](i32 42), !callees [[META0:![0-9]+]] 182; LIMI2-NEXT: br label [[TMP7]] 183; LIMI2: 7: 184; LIMI2-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP6]] ] 185; LIMI2-NEXT: ret i32 [[CALL_PHI]] 186; 187; LIMI0-LABEL: @non_matching_fp1( 188; LIMI0-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 189; LIMI0-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void 190; LIMI0-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 191; LIMI0-NEXT: [[CALL:%.*]] = call i32 [[FP]](i32 42), !callees [[META2:![0-9]+]] 192; LIMI0-NEXT: ret i32 [[CALL]] 193; 194 %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32 195 %fp2 = select i1 %c2, ptr @retFloatTakeFloat, ptr @void 196 %fp = select i1 %c, ptr %fp1, ptr %fp2 197 %call = call i32 %fp(i32 42) 198 ret i32 %call 199} 200 201define i32 @non_matching_fp1_noundef(i1 %c1, i1 %c2, i1 %c) { 202; UNLIM-LABEL: @non_matching_fp1_noundef( 203; UNLIM-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 204; UNLIM-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void 205; UNLIM-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 206; UNLIM-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 207; UNLIM-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 208; UNLIM: 2: 209; UNLIM-NEXT: [[CALL1:%.*]] = call i32 @takeI32(i32 42) 210; UNLIM-NEXT: br label [[TMP9:%.*]] 211; UNLIM: 3: 212; UNLIM-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 213; UNLIM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 214; UNLIM: 5: 215; UNLIM-NEXT: [[CALL2:%.*]] = call i32 @retI32(i32 42) 216; UNLIM-NEXT: br label [[TMP9]] 217; UNLIM: 6: 218; UNLIM-NEXT: br i1 true, label [[TMP7:%.*]], label [[TMP8:%.*]] 219; UNLIM: 7: 220; UNLIM-NEXT: [[CALL3:%.*]] = call i32 @void(i32 42) 221; UNLIM-NEXT: br label [[TMP9]] 222; UNLIM: 8: 223; UNLIM-NEXT: unreachable 224; UNLIM: 9: 225; UNLIM-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP7]] ] 226; UNLIM-NEXT: ret i32 [[CALL_PHI]] 227; 228; LIMI2-LABEL: @non_matching_fp1_noundef( 229; LIMI2-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 230; LIMI2-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void 231; LIMI2-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 232; LIMI2-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 233; LIMI2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 234; LIMI2: 2: 235; LIMI2-NEXT: [[CALL1:%.*]] = call i32 @takeI32(i32 42) 236; LIMI2-NEXT: br label [[TMP7:%.*]] 237; LIMI2: 3: 238; LIMI2-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 239; LIMI2-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 240; LIMI2: 5: 241; LIMI2-NEXT: [[CALL2:%.*]] = call i32 @retI32(i32 42) 242; LIMI2-NEXT: br label [[TMP7]] 243; LIMI2: 6: 244; LIMI2-NEXT: [[CALL3:%.*]] = call i32 [[FP]](i32 42), !callees [[META1:![0-9]+]] 245; LIMI2-NEXT: br label [[TMP7]] 246; LIMI2: 7: 247; LIMI2-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP6]] ] 248; LIMI2-NEXT: ret i32 [[CALL_PHI]] 249; 250; LIMI0-LABEL: @non_matching_fp1_noundef( 251; LIMI0-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 252; LIMI0-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void 253; LIMI0-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 254; LIMI0-NEXT: [[CALL:%.*]] = call i32 [[FP]](i32 42), !callees [[META3:![0-9]+]] 255; LIMI0-NEXT: ret i32 [[CALL]] 256; 257 %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32 258 %fp2 = select i1 %c2, ptr @retFloatTakeFloatFloatNoundef, ptr @void 259 %fp = select i1 %c, ptr %fp1, ptr %fp2 260 %call = call i32 %fp(i32 42) 261 ret i32 %call 262} 263 264define void @non_matching_fp2(i1 %c1, i1 %c2, i1 %c, ptr %unknown) { 265; OUNLM-LABEL: @non_matching_fp2( 266; OUNLM-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 267; OUNLM-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]] 268; OUNLM-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 269; OUNLM-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 270; OUNLM-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 271; OUNLM: 2: 272; OUNLM-NEXT: call void @takeI32() 273; OUNLM-NEXT: br label [[TMP10:%.*]] 274; OUNLM: 3: 275; OUNLM-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 276; OUNLM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 277; OUNLM: 5: 278; OUNLM-NEXT: call void @retI32() 279; OUNLM-NEXT: br label [[TMP10]] 280; OUNLM: 6: 281; OUNLM-NEXT: [[TMP7:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat 282; OUNLM-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]] 283; OUNLM: 8: 284; OUNLM-NEXT: call void @retFloatTakeFloat() 285; OUNLM-NEXT: br label [[TMP10]] 286; OUNLM: 9: 287; OUNLM-NEXT: call void [[FP]]() 288; OUNLM-NEXT: br label [[TMP10]] 289; OUNLM: 10: 290; OUNLM-NEXT: ret void 291; 292; LIMI2-LABEL: @non_matching_fp2( 293; LIMI2-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 294; LIMI2-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]] 295; LIMI2-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 296; LIMI2-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 297; LIMI2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 298; LIMI2: 2: 299; LIMI2-NEXT: call void @takeI32() 300; LIMI2-NEXT: br label [[TMP7:%.*]] 301; LIMI2: 3: 302; LIMI2-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 303; LIMI2-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 304; LIMI2: 5: 305; LIMI2-NEXT: call void @retI32() 306; LIMI2-NEXT: br label [[TMP7]] 307; LIMI2: 6: 308; LIMI2-NEXT: call void [[FP]]() 309; LIMI2-NEXT: br label [[TMP7]] 310; LIMI2: 7: 311; LIMI2-NEXT: ret void 312; 313; LIMI0-LABEL: @non_matching_fp2( 314; LIMI0-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 315; LIMI0-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]] 316; LIMI0-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 317; LIMI0-NEXT: call void [[FP]]() 318; LIMI0-NEXT: ret void 319; 320; CWRLD-LABEL: @non_matching_fp2( 321; CWRLD-NEXT: [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32 322; CWRLD-NEXT: [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]] 323; CWRLD-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]] 324; CWRLD-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32 325; CWRLD-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 326; CWRLD: 2: 327; CWRLD-NEXT: call void @takeI32() 328; CWRLD-NEXT: br label [[TMP21:%.*]] 329; CWRLD: 3: 330; CWRLD-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32 331; CWRLD-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 332; CWRLD: 5: 333; CWRLD-NEXT: call void @retI32() 334; CWRLD-NEXT: br label [[TMP21]] 335; CWRLD: 6: 336; CWRLD-NEXT: [[TMP7:%.*]] = icmp eq ptr [[FP]], @func3 337; CWRLD-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]] 338; CWRLD: 8: 339; CWRLD-NEXT: call void @func3() 340; CWRLD-NEXT: br label [[TMP21]] 341; CWRLD: 9: 342; CWRLD-NEXT: [[TMP10:%.*]] = icmp eq ptr [[FP]], @func4 343; CWRLD-NEXT: br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]] 344; CWRLD: 11: 345; CWRLD-NEXT: call void @func4() 346; CWRLD-NEXT: br label [[TMP21]] 347; CWRLD: 12: 348; CWRLD-NEXT: [[TMP13:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat 349; CWRLD-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]] 350; CWRLD: 14: 351; CWRLD-NEXT: call void @retFloatTakeFloat() 352; CWRLD-NEXT: br label [[TMP21]] 353; CWRLD: 15: 354; CWRLD-NEXT: [[TMP16:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloatFloatNoundef 355; CWRLD-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]] 356; CWRLD: 17: 357; CWRLD-NEXT: call void @retFloatTakeFloatFloatNoundef() 358; CWRLD-NEXT: br label [[TMP21]] 359; CWRLD: 18: 360; CWRLD-NEXT: br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]] 361; CWRLD: 19: 362; CWRLD-NEXT: call void @void() 363; CWRLD-NEXT: br label [[TMP21]] 364; CWRLD: 20: 365; CWRLD-NEXT: unreachable 366; CWRLD: 21: 367; CWRLD-NEXT: ret void 368; 369 %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32 370 %fp2 = select i1 %c2, ptr @retFloatTakeFloat, ptr %unknown 371 %fp = select i1 %c, ptr %fp1, ptr %fp2 372 call void %fp() 373 ret void 374} 375 376define i32 @non_matching_unknown(i1 %c, ptr %fn) { 377; OUNLM-LABEL: @non_matching_unknown( 378; OUNLM-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]] 379; OUNLM-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32 380; OUNLM-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 381; OUNLM: 2: 382; OUNLM-NEXT: [[CALL1:%.*]] = call i32 @retI32(i32 42) 383; OUNLM-NEXT: br label [[TMP4:%.*]] 384; OUNLM: 3: 385; OUNLM-NEXT: [[CALL2:%.*]] = call i32 [[FP]](i32 42) 386; OUNLM-NEXT: br label [[TMP4]] 387; OUNLM: 4: 388; OUNLM-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ] 389; OUNLM-NEXT: ret i32 [[CALL_PHI]] 390; 391; LIMI2-LABEL: @non_matching_unknown( 392; LIMI2-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]] 393; LIMI2-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32 394; LIMI2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 395; LIMI2: 2: 396; LIMI2-NEXT: [[CALL1:%.*]] = call i32 @retI32(i32 42) 397; LIMI2-NEXT: br label [[TMP4:%.*]] 398; LIMI2: 3: 399; LIMI2-NEXT: [[CALL2:%.*]] = call i32 [[FP]](i32 42) 400; LIMI2-NEXT: br label [[TMP4]] 401; LIMI2: 4: 402; LIMI2-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ] 403; LIMI2-NEXT: ret i32 [[CALL_PHI]] 404; 405; LIMI0-LABEL: @non_matching_unknown( 406; LIMI0-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]] 407; LIMI0-NEXT: [[CALL:%.*]] = call i32 [[FP]](i32 42) 408; LIMI0-NEXT: ret i32 [[CALL]] 409; 410; CWRLD-LABEL: @non_matching_unknown( 411; CWRLD-NEXT: [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]] 412; CWRLD-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @func3 413; CWRLD-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 414; CWRLD: 2: 415; CWRLD-NEXT: [[CALL1:%.*]] = call i32 @func3(i32 42) 416; CWRLD-NEXT: br label [[TMP24:%.*]] 417; CWRLD: 3: 418; CWRLD-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP]], @func4 419; CWRLD-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 420; CWRLD: 5: 421; CWRLD-NEXT: [[CALL2:%.*]] = call i32 @func4(i32 42) 422; CWRLD-NEXT: br label [[TMP24]] 423; CWRLD: 6: 424; CWRLD-NEXT: [[TMP7:%.*]] = icmp eq ptr [[FP]], @retI32 425; CWRLD-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]] 426; CWRLD: 8: 427; CWRLD-NEXT: [[CALL3:%.*]] = call i32 @retI32(i32 42) 428; CWRLD-NEXT: br label [[TMP24]] 429; CWRLD: 9: 430; CWRLD-NEXT: [[TMP10:%.*]] = icmp eq ptr [[FP]], @takeI32 431; CWRLD-NEXT: br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]] 432; CWRLD: 11: 433; CWRLD-NEXT: [[CALL4:%.*]] = call i32 @takeI32(i32 42) 434; CWRLD-NEXT: br label [[TMP24]] 435; CWRLD: 12: 436; CWRLD-NEXT: [[TMP13:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat 437; CWRLD-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP18:%.*]] 438; CWRLD: 14: 439; CWRLD-NEXT: [[TMP15:%.*]] = bitcast i32 42 to float 440; CWRLD-NEXT: [[TMP16:%.*]] = call float @retFloatTakeFloat(float [[TMP15]]) 441; CWRLD-NEXT: [[TMP17:%.*]] = bitcast float [[TMP16]] to i32 442; CWRLD-NEXT: br label [[TMP24]] 443; CWRLD: 18: 444; CWRLD-NEXT: [[TMP19:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloatFloatNoundef 445; CWRLD-NEXT: br i1 [[TMP19]], label [[TMP20:%.*]], label [[TMP21:%.*]] 446; CWRLD: 20: 447; CWRLD-NEXT: [[CALL5:%.*]] = call i32 @retFloatTakeFloatFloatNoundef(i32 42) 448; CWRLD-NEXT: br label [[TMP24]] 449; CWRLD: 21: 450; CWRLD-NEXT: br i1 true, label [[TMP22:%.*]], label [[TMP23:%.*]] 451; CWRLD: 22: 452; CWRLD-NEXT: [[CALL6:%.*]] = call i32 @void(i32 42) 453; CWRLD-NEXT: br label [[TMP24]] 454; CWRLD: 23: 455; CWRLD-NEXT: unreachable 456; CWRLD: 24: 457; CWRLD-NEXT: [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP8]] ], [ [[CALL4]], [[TMP11]] ], [ [[TMP17]], [[TMP14]] ], [ [[CALL5]], [[TMP20]] ], [ [[CALL6]], [[TMP22]] ] 458; CWRLD-NEXT: ret i32 [[CALL_PHI]] 459; 460 %fp = select i1 %c, ptr @retI32, ptr %fn 461 %call = call i32 %fp(i32 42) 462 ret i32 %call 463} 464 465; This function is used in a "direct" call but with a different signature. 466; We check that it does not show up above in any of the if-cascades because 467; the address is not actually taken. 468declare void @usedOnlyInCastedDirectCall(i32) 469define void @usedOnlyInCastedDirectCallCaller() { 470; CHECK-LABEL: @usedOnlyInCastedDirectCallCaller( 471; CHECK-NEXT: call void @usedOnlyInCastedDirectCall() 472; CHECK-NEXT: ret void 473; 474 call void @usedOnlyInCastedDirectCall() 475 ret void 476} 477 478define internal void @usedByGlobal() { 479; CHECK-LABEL: @usedByGlobal( 480; CHECK-NEXT: ret void 481; 482 ret void 483} 484@G = global ptr @usedByGlobal 485 486define void @broker(ptr %unknown) !callback !0 { 487; OWRDL-LABEL: @broker( 488; OWRDL-NEXT: call void [[UNKNOWN:%.*]]() 489; OWRDL-NEXT: ret void 490; 491; CWRLD-LABEL: @broker( 492; CWRLD-NEXT: [[TMP1:%.*]] = icmp eq ptr [[UNKNOWN:%.*]], @func3 493; CWRLD-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 494; CWRLD: 2: 495; CWRLD-NEXT: call void @func3() 496; CWRLD-NEXT: br label [[TMP21:%.*]] 497; CWRLD: 3: 498; CWRLD-NEXT: [[TMP4:%.*]] = icmp eq ptr [[UNKNOWN]], @func4 499; CWRLD-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 500; CWRLD: 5: 501; CWRLD-NEXT: call void @func4() 502; CWRLD-NEXT: br label [[TMP21]] 503; CWRLD: 6: 504; CWRLD-NEXT: [[TMP7:%.*]] = icmp eq ptr [[UNKNOWN]], @retI32 505; CWRLD-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]] 506; CWRLD: 8: 507; CWRLD-NEXT: call void @retI32() 508; CWRLD-NEXT: br label [[TMP21]] 509; CWRLD: 9: 510; CWRLD-NEXT: [[TMP10:%.*]] = icmp eq ptr [[UNKNOWN]], @takeI32 511; CWRLD-NEXT: br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]] 512; CWRLD: 11: 513; CWRLD-NEXT: call void @takeI32() 514; CWRLD-NEXT: br label [[TMP21]] 515; CWRLD: 12: 516; CWRLD-NEXT: [[TMP13:%.*]] = icmp eq ptr [[UNKNOWN]], @retFloatTakeFloat 517; CWRLD-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]] 518; CWRLD: 14: 519; CWRLD-NEXT: call void @retFloatTakeFloat() 520; CWRLD-NEXT: br label [[TMP21]] 521; CWRLD: 15: 522; CWRLD-NEXT: [[TMP16:%.*]] = icmp eq ptr [[UNKNOWN]], @retFloatTakeFloatFloatNoundef 523; CWRLD-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]] 524; CWRLD: 17: 525; CWRLD-NEXT: call void @retFloatTakeFloatFloatNoundef() 526; CWRLD-NEXT: br label [[TMP21]] 527; CWRLD: 18: 528; CWRLD-NEXT: br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]] 529; CWRLD: 19: 530; CWRLD-NEXT: call void @void() 531; CWRLD-NEXT: br label [[TMP21]] 532; CWRLD: 20: 533; CWRLD-NEXT: unreachable 534; CWRLD: 21: 535; CWRLD-NEXT: ret void 536; 537 call void %unknown() 538 ret void 539} 540 541define void @func6() { 542; CHECK-LABEL: @func6( 543; CHECK-NEXT: call void @broker(ptr nofree noundef nonnull captures(none) @func3) 544; CHECK-NEXT: ret void 545; 546 call void @broker(ptr @func3) 547 ret void 548} 549 550; Cannot be internal_good as it is internal and we see all uses. 551; Can be func4 since it escapes. 552define void @func7(ptr %unknown) { 553; UPTO2-LABEL: @func7( 554; UPTO2-NEXT: [[TMP1:%.*]] = icmp eq ptr [[UNKNOWN:%.*]], @func3 555; UPTO2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 556; UPTO2: 2: 557; UPTO2-NEXT: call void @func3() 558; UPTO2-NEXT: br label [[TMP6:%.*]] 559; UPTO2: 3: 560; UPTO2-NEXT: br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]] 561; UPTO2: 4: 562; UPTO2-NEXT: call void @func4() 563; UPTO2-NEXT: br label [[TMP6]] 564; UPTO2: 5: 565; UPTO2-NEXT: unreachable 566; UPTO2: 6: 567; UPTO2-NEXT: ret void 568; 569; LIMI0-LABEL: @func7( 570; LIMI0-NEXT: call void [[UNKNOWN:%.*]](), !callees [[META1]] 571; LIMI0-NEXT: ret void 572; 573 call void %unknown(), !callees !2 574 ret void 575} 576 577; Check there's no crash if something that isn't a function appears in !callees 578define void @undef_in_callees() { 579; UNLIM-LABEL: @undef_in_callees( 580; UNLIM-NEXT: cond.end.i: 581; UNLIM-NEXT: call void undef(ptr undef, i32 undef, ptr undef), !callees [[META2:![0-9]+]] 582; UNLIM-NEXT: ret void 583; 584; LIMI2-LABEL: @undef_in_callees( 585; LIMI2-NEXT: cond.end.i: 586; LIMI2-NEXT: call void undef(ptr undef, i32 undef, ptr undef), !callees [[META4:![0-9]+]] 587; LIMI2-NEXT: ret void 588; 589; LIMI0-LABEL: @undef_in_callees( 590; LIMI0-NEXT: cond.end.i: 591; LIMI0-NEXT: call void undef(ptr undef, i32 undef, ptr undef), !callees [[META6:![0-9]+]] 592; LIMI0-NEXT: ret void 593; 594cond.end.i: 595 call void undef(ptr undef, i32 undef, ptr undef), !callees !3 596 ret void 597} 598 599define void @as_cast(ptr %arg) { 600; OWRDL-LABEL: @as_cast( 601; OWRDL-NEXT: [[FP:%.*]] = load ptr addrspace(1), ptr [[ARG:%.*]], align 8 602; OWRDL-NEXT: tail call addrspace(1) void [[FP]]() 603; OWRDL-NEXT: ret void 604; 605; CWRLD-LABEL: @as_cast( 606; CWRLD-NEXT: [[FP:%.*]] = load ptr addrspace(1), ptr [[ARG:%.*]], align 8 607; CWRLD-NEXT: [[FP_AS0:%.*]] = addrspacecast ptr addrspace(1) [[FP]] to ptr 608; CWRLD-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP_AS0]], @func3 609; CWRLD-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] 610; CWRLD: 2: 611; CWRLD-NEXT: tail call void @func3() 612; CWRLD-NEXT: br label [[TMP21:%.*]] 613; CWRLD: 3: 614; CWRLD-NEXT: [[TMP4:%.*]] = icmp eq ptr [[FP_AS0]], @func4 615; CWRLD-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] 616; CWRLD: 5: 617; CWRLD-NEXT: tail call void @func4() 618; CWRLD-NEXT: br label [[TMP21]] 619; CWRLD: 6: 620; CWRLD-NEXT: [[TMP7:%.*]] = icmp eq ptr [[FP_AS0]], @retI32 621; CWRLD-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]] 622; CWRLD: 8: 623; CWRLD-NEXT: call void @retI32() 624; CWRLD-NEXT: br label [[TMP21]] 625; CWRLD: 9: 626; CWRLD-NEXT: [[TMP10:%.*]] = icmp eq ptr [[FP_AS0]], @takeI32 627; CWRLD-NEXT: br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]] 628; CWRLD: 11: 629; CWRLD-NEXT: call void @takeI32() 630; CWRLD-NEXT: br label [[TMP21]] 631; CWRLD: 12: 632; CWRLD-NEXT: [[TMP13:%.*]] = icmp eq ptr [[FP_AS0]], @retFloatTakeFloat 633; CWRLD-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]] 634; CWRLD: 14: 635; CWRLD-NEXT: call void @retFloatTakeFloat() 636; CWRLD-NEXT: br label [[TMP21]] 637; CWRLD: 15: 638; CWRLD-NEXT: [[TMP16:%.*]] = icmp eq ptr [[FP_AS0]], @retFloatTakeFloatFloatNoundef 639; CWRLD-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]] 640; CWRLD: 17: 641; CWRLD-NEXT: call void @retFloatTakeFloatFloatNoundef() 642; CWRLD-NEXT: br label [[TMP21]] 643; CWRLD: 18: 644; CWRLD-NEXT: br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]] 645; CWRLD: 19: 646; CWRLD-NEXT: tail call void @void() 647; CWRLD-NEXT: br label [[TMP21]] 648; CWRLD: 20: 649; CWRLD-NEXT: unreachable 650; CWRLD: 21: 651; CWRLD-NEXT: ret void 652; 653 %fp = load ptr addrspace(1), ptr %arg, align 8 654 tail call addrspace(1) void %fp() 655 ret void 656} 657 658!0 = !{!1} 659!1 = !{i64 0, i1 false} 660!2 = !{ptr @func3, ptr @func4} 661!3 = distinct !{ptr undef, ptr null} 662 663; UTC_ARGS: --disable 664 665; DOT-DAG: Node[[FUNC1:0x[a-z0-9]+]] [shape=record,label="{func1}"]; 666; DOT-DAG: Node[[FUNC2:0x[a-z0-9]+]] [shape=record,label="{func2}"]; 667; DOT-DAG: Node[[FUNC3:0x[a-z0-9]+]] [shape=record,label="{func3}"]; 668; DOT-DAG: Node[[FUNC4:0x[a-z0-9]+]] [shape=record,label="{func4}"]; 669; DOT-DAG: Node[[FUNC5:0x[a-z0-9]+]] [shape=record,label="{func5}"]; 670; DOT-DAG: Node[[FUNC6:0x[a-z0-9]+]] [shape=record,label="{func6}"]; 671; DOT-DAG: Node[[FUNC7:0x[a-z0-9]+]] [shape=record,label="{func7}"]; 672 673; DOT-DAG: Node[[BROKER:0x[a-z0-9]+]] [shape=record,label="{broker}"]; 674 675; DOT-DAG: Node[[FUNC1]] -> Node[[FUNC3]]; 676; DOT-DAG: Node[[FUNC2]] -> Node[[FUNC4]]; 677; DOT-DAG: Node[[FUNC5]] -> Node[[FUNC3]]; 678; DOT-DAG: Node[[FUNC5]] -> Node[[FUNC4]]; 679 680; DOT-DAG: Node[[FUNC6]] -> Node[[BROKER]]; 681 682; This one gets added because of the callback metadata. 683; DOT-DAG: Node[[FUNC6]] -> Node[[FUNC3]]; 684 685; These ones are added because of the callees metadata. 686; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC3]]; 687; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC4]]; 688 689; UTC_ARGS: --enable 690 691;. 692; OUNLM: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 693;. 694; LIMI2: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 695;. 696; LIMI0: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 697;. 698; CWRLD: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 699;. 700; OUNLM: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]} 701; OUNLM: [[META1]] = !{i64 0, i1 false} 702; OUNLM: [[META2]] = distinct !{ptr undef, ptr null} 703;. 704; LIMI2: [[META0]] = !{ptr @void, ptr @retFloatTakeFloat} 705; LIMI2: [[META1]] = !{ptr @void} 706; LIMI2: [[META2:![0-9]+]] = !{[[META3:![0-9]+]]} 707; LIMI2: [[META3]] = !{i64 0, i1 false} 708; LIMI2: [[META4]] = distinct !{ptr undef, ptr null} 709;. 710; LIMI0: [[META0]] = !{ptr @func4, ptr @internal_good} 711; LIMI0: [[META1]] = !{ptr @func3, ptr @func4} 712; LIMI0: [[META2]] = !{ptr @takeI32, ptr @retI32, ptr @void, ptr @retFloatTakeFloat} 713; LIMI0: [[META3]] = !{ptr @takeI32, ptr @retI32, ptr @void} 714; LIMI0: [[META4:![0-9]+]] = !{[[META5:![0-9]+]]} 715; LIMI0: [[META5]] = !{i64 0, i1 false} 716; LIMI0: [[META6]] = distinct !{ptr undef, ptr null} 717;. 718; CWRLD: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]} 719; CWRLD: [[META1]] = !{i64 0, i1 false} 720; CWRLD: [[META2]] = distinct !{ptr undef, ptr null} 721;. 722;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 723; DOT: {{.*}} 724