1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts -S | FileCheck %s 3; RUN: opt --try-experimental-debuginfo-iterators < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts -S | FileCheck %s 4; RUN: opt < %s -passes='simplifycfg<sink-common-insts>' -S | FileCheck %s 5; RUN: opt --try-experimental-debuginfo-iterators < %s -passes='simplifycfg<sink-common-insts>' -S | FileCheck %s 6 7target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 8target triple = "x86_64-pc-linux-gnu" 9 10define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 11; CHECK-LABEL: @test1( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS:%.*]], [[BLKSB:%.*]] 14; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA:%.*]] 15; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA]], [[NBLKS]] 16; CHECK-NEXT: [[CMP2_SINK:%.*]] = select i1 [[FLAG:%.*]], i1 [[CMP]], i1 [[CMP2]] 17; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8 18; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL3]], 0 19; CHECK-NEXT: ret i1 [[TOBOOL4]] 20; 21entry: 22 br i1 %flag, label %if.then, label %if.else 23 24if.then: 25 %cmp = icmp uge i32 %blksA, %nblks 26 %frombool1 = zext i1 %cmp to i8 27 br label %if.end 28 29if.else: 30 %add = add i32 %nblks, %blksB 31 %cmp2 = icmp ule i32 %add, %blksA 32 %frombool3 = zext i1 %cmp2 to i8 33 br label %if.end 34 35if.end: 36 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ] 37 %tobool4 = icmp ne i8 %obeys.0, 0 38 ret i1 %tobool4 39} 40 41define zeroext i1 @test2(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 42; CHECK-LABEL: @test2( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS:%.*]], [[BLKSB:%.*]] 45; CHECK-NEXT: [[ADD_SINK:%.*]] = select i1 [[FLAG:%.*]], i32 [[NBLKS]], i32 [[ADD]] 46; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[ADD_SINK]] 47; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8 48; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL3]], 0 49; CHECK-NEXT: ret i1 [[TOBOOL4]] 50; 51entry: 52 br i1 %flag, label %if.then, label %if.else 53 54if.then: 55 %cmp = icmp uge i32 %blksA, %nblks 56 %frombool1 = zext i1 %cmp to i8 57 br label %if.end 58 59if.else: 60 %add = add i32 %nblks, %blksB 61 %cmp2 = icmp uge i32 %blksA, %add 62 %frombool3 = zext i1 %cmp2 to i8 63 br label %if.end 64 65if.end: 66 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ] 67 %tobool4 = icmp ne i8 %obeys.0, 0 68 ret i1 %tobool4 69} 70 71declare i32 @foo(i32, i32) nounwind readnone 72 73define i32 @test3(i1 zeroext %flag, i32 %x, i32 %y) { 74; CHECK-LABEL: @test3( 75; CHECK-NEXT: entry: 76; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 77; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0:[0-9]+]] 78; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]] 79; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Y1]] 80; CHECK-NEXT: ret i32 [[RET]] 81; 82entry: 83 br i1 %flag, label %if.then, label %if.else 84 85if.then: 86 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone 87 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone 88 br label %if.end 89 90if.else: 91 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone 92 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone 93 br label %if.end 94 95if.end: 96 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] 97 %yy = phi i32 [ %y0, %if.then ], [ %y1, %if.else ] 98 %ret = add i32 %xx, %yy 99 ret i32 %ret 100} 101 102 103define i32 @test4(i1 zeroext %flag, i32 %x, ptr %y) { 104; CHECK-LABEL: @test4( 105; CHECK-NEXT: entry: 106; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 107; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], [[DOT]] 108; CHECK-NEXT: store i32 [[B]], ptr [[Y:%.*]], align 4 109; CHECK-NEXT: ret i32 1 110; 111entry: 112 br i1 %flag, label %if.then, label %if.else 113 114if.then: 115 %a = add i32 %x, 5 116 store i32 %a, ptr %y 117 br label %if.end 118 119if.else: 120 %b = add i32 %x, 7 121 store i32 %b, ptr %y 122 br label %if.end 123 124if.end: 125 ret i32 1 126} 127 128 129define i32 @test5(i1 zeroext %flag, i32 %x, ptr %y) { 130; CHECK-LABEL: @test5( 131; CHECK-NEXT: entry: 132; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 133; CHECK: if.then: 134; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 5 135; CHECK-NEXT: store volatile i32 [[A]], ptr [[Y:%.*]], align 4 136; CHECK-NEXT: br label [[IF_END:%.*]] 137; CHECK: if.else: 138; CHECK-NEXT: [[B:%.*]] = add i32 [[X]], 7 139; CHECK-NEXT: store i32 [[B]], ptr [[Y]], align 4 140; CHECK-NEXT: br label [[IF_END]] 141; CHECK: if.end: 142; CHECK-NEXT: ret i32 1 143; 144entry: 145 br i1 %flag, label %if.then, label %if.else 146 147if.then: 148 %a = add i32 %x, 5 149 store volatile i32 %a, ptr %y 150 br label %if.end 151 152if.else: 153 %b = add i32 %x, 7 154 store i32 %b, ptr %y 155 br label %if.end 156 157if.end: 158 ret i32 1 159} 160 161 162define i32 @test6(i1 zeroext %flag, i32 %x, ptr %y) { 163; CHECK-LABEL: @test6( 164; CHECK-NEXT: entry: 165; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 166; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], [[DOT]] 167; CHECK-NEXT: store volatile i32 [[B]], ptr [[Y:%.*]], align 4 168; CHECK-NEXT: ret i32 1 169; 170entry: 171 br i1 %flag, label %if.then, label %if.else 172 173if.then: 174 %a = add i32 %x, 5 175 store volatile i32 %a, ptr %y 176 br label %if.end 177 178if.else: 179 %b = add i32 %x, 7 180 store volatile i32 %b, ptr %y 181 br label %if.end 182 183if.end: 184 ret i32 1 185} 186 187 188define i32 @test7(i1 zeroext %flag, i32 %x, ptr %y) { 189; CHECK-LABEL: @test7( 190; CHECK-NEXT: entry: 191; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 192; CHECK-NEXT: [[W:%.*]] = load volatile i32, ptr [[Y:%.*]], align 4 193; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], [[DOT]] 194; CHECK-NEXT: store volatile i32 [[B]], ptr [[Y]], align 4 195; CHECK-NEXT: ret i32 1 196; 197entry: 198 br i1 %flag, label %if.then, label %if.else 199 200if.then: 201 %z = load volatile i32, ptr %y 202 %a = add i32 %z, 5 203 store volatile i32 %a, ptr %y 204 br label %if.end 205 206if.else: 207 %w = load volatile i32, ptr %y 208 %b = add i32 %w, 7 209 store volatile i32 %b, ptr %y 210 br label %if.end 211 212if.end: 213 ret i32 1 214} 215 216 217; %z and %w are in different blocks. We shouldn't sink the add because 218; there may be intervening memory instructions. 219define i32 @test8(i1 zeroext %flag, i32 %x, ptr %y) { 220; CHECK-LABEL: @test8( 221; CHECK-NEXT: entry: 222; CHECK-NEXT: [[Z:%.*]] = load volatile i32, ptr [[Y:%.*]], align 4 223; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 224; CHECK: if.then: 225; CHECK-NEXT: [[A:%.*]] = add i32 [[Z]], 5 226; CHECK-NEXT: br label [[IF_END:%.*]] 227; CHECK: if.else: 228; CHECK-NEXT: [[W:%.*]] = load volatile i32, ptr [[Y]], align 4 229; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], 7 230; CHECK-NEXT: br label [[IF_END]] 231; CHECK: if.end: 232; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[B]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ] 233; CHECK-NEXT: store volatile i32 [[B_SINK]], ptr [[Y]], align 4 234; CHECK-NEXT: ret i32 1 235; 236entry: 237 %z = load volatile i32, ptr %y 238 br i1 %flag, label %if.then, label %if.else 239 240if.then: 241 %a = add i32 %z, 5 242 store volatile i32 %a, ptr %y 243 br label %if.end 244 245if.else: 246 %w = load volatile i32, ptr %y 247 %b = add i32 %w, 7 248 store volatile i32 %b, ptr %y 249 br label %if.end 250 251if.end: 252 ret i32 1 253} 254 255 256; The extra store in %if.then means %z and %w are not equivalent. 257define i32 @test9(i1 zeroext %flag, i32 %x, ptr %y, ptr %p) { 258; CHECK-LABEL: @test9( 259; CHECK-NEXT: entry: 260; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 261; CHECK: if.then: 262; CHECK-NEXT: store i32 7, ptr [[P:%.*]], align 4 263; CHECK-NEXT: [[Z:%.*]] = load volatile i32, ptr [[Y:%.*]], align 4 264; CHECK-NEXT: store i32 6, ptr [[P]], align 4 265; CHECK-NEXT: [[A:%.*]] = add i32 [[Z]], 5 266; CHECK-NEXT: br label [[IF_END:%.*]] 267; CHECK: if.else: 268; CHECK-NEXT: [[W:%.*]] = load volatile i32, ptr [[Y]], align 4 269; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], 7 270; CHECK-NEXT: br label [[IF_END]] 271; CHECK: if.end: 272; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[B]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ] 273; CHECK-NEXT: store volatile i32 [[B_SINK]], ptr [[Y]], align 4 274; CHECK-NEXT: ret i32 1 275; 276entry: 277 br i1 %flag, label %if.then, label %if.else 278 279if.then: 280 store i32 7, ptr %p 281 %z = load volatile i32, ptr %y 282 store i32 6, ptr %p 283 %a = add i32 %z, 5 284 store volatile i32 %a, ptr %y 285 br label %if.end 286 287if.else: 288 %w = load volatile i32, ptr %y 289 %b = add i32 %w, 7 290 store volatile i32 %b, ptr %y 291 br label %if.end 292 293if.end: 294 ret i32 1 295} 296 297 298%struct.anon = type { i32, i32 } 299 300; The GEP indexes a struct type so cannot have a variable last index. 301define i32 @test10(i1 zeroext %flag, i32 %x, ptr %y, ptr %s) { 302; CHECK-LABEL: @test10( 303; CHECK-NEXT: entry: 304; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 305; CHECK: if.then: 306; CHECK-NEXT: call void @bar(i32 5) 307; CHECK-NEXT: store volatile i32 [[X:%.*]], ptr [[S:%.*]], align 4 308; CHECK-NEXT: br label [[IF_END:%.*]] 309; CHECK: if.else: 310; CHECK-NEXT: call void @bar(i32 6) 311; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[S]], i32 0, i32 1 312; CHECK-NEXT: store volatile i32 [[X]], ptr [[GEPB]], align 4 313; CHECK-NEXT: br label [[IF_END]] 314; CHECK: if.end: 315; CHECK-NEXT: ret i32 1 316; 317entry: 318 br i1 %flag, label %if.then, label %if.else 319 320if.then: 321 call void @bar(i32 5) 322 store volatile i32 %x, ptr %s 323 br label %if.end 324 325if.else: 326 call void @bar(i32 6) 327 %gepb = getelementptr inbounds %struct.anon, ptr %s, i32 0, i32 1 328 store volatile i32 %x, ptr %gepb 329 br label %if.end 330 331if.end: 332 ret i32 1 333} 334 335 336; The shufflevector's mask operand cannot be merged in a PHI. 337define i32 @test11(i1 zeroext %flag, i32 %w, <2 x i32> %x, <2 x i32> %y) { 338; CHECK-LABEL: @test11( 339; CHECK-NEXT: entry: 340; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 341; CHECK: if.then: 342; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5 343; CHECK-NEXT: [[SV1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 0, i32 1> 344; CHECK-NEXT: br label [[IF_END:%.*]] 345; CHECK: if.else: 346; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6 347; CHECK-NEXT: [[SV2:%.*]] = shufflevector <2 x i32> [[X]], <2 x i32> [[Y]], <2 x i32> <i32 1, i32 0> 348; CHECK-NEXT: br label [[IF_END]] 349; CHECK: if.end: 350; CHECK-NEXT: [[P:%.*]] = phi <2 x i32> [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 351; CHECK-NEXT: ret i32 1 352; 353entry: 354 br i1 %flag, label %if.then, label %if.else 355 356if.then: 357 %dummy = add i32 %w, 5 358 %sv1 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 0, i32 1> 359 br label %if.end 360 361if.else: 362 %dummy1 = add i32 %w, 6 363 %sv2 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 1, i32 0> 364 br label %if.end 365 366if.end: 367 %p = phi <2 x i32> [ %sv1, %if.then ], [ %sv2, %if.else ] 368 ret i32 1 369} 370 371 372; We can't common an intrinsic! 373define i32 @test12(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) { 374; CHECK-LABEL: @test12( 375; CHECK-NEXT: entry: 376; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 377; CHECK: if.then: 378; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5 379; CHECK-NEXT: [[SV1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 380; CHECK-NEXT: br label [[IF_END:%.*]] 381; CHECK: if.else: 382; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6 383; CHECK-NEXT: [[SV2:%.*]] = call i32 @llvm.cttz.i32(i32 [[X]], i1 false) 384; CHECK-NEXT: br label [[IF_END]] 385; CHECK: if.end: 386; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 387; CHECK-NEXT: ret i32 1 388; 389entry: 390 br i1 %flag, label %if.then, label %if.else 391 392if.then: 393 %dummy = add i32 %w, 5 394 %sv1 = call i32 @llvm.ctlz.i32(i32 %x, i1 false) 395 br label %if.end 396 397if.else: 398 %dummy1 = add i32 %w, 6 399 %sv2 = call i32 @llvm.cttz.i32(i32 %x, i1 false) 400 br label %if.end 401 402if.end: 403 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ] 404 ret i32 1 405} 406 407declare i32 @llvm.ctlz.i32(i32 %x, i1 immarg) readnone 408declare i32 @llvm.cttz.i32(i32 %x, i1 immarg) readnone 409 410 411; The TBAA metadata should be properly combined. 412define i32 @test13(i1 zeroext %flag, i32 %x, ptr %y) { 413; CHECK-LABEL: @test13( 414; CHECK-NEXT: entry: 415; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 416; CHECK-NEXT: [[W:%.*]] = load volatile i32, ptr [[Y:%.*]], align 4 417; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], [[DOT]] 418; CHECK-NEXT: store volatile i32 [[B]], ptr [[Y]], align 4, !tbaa [[TBAA4:![0-9]+]] 419; CHECK-NEXT: ret i32 1 420; 421entry: 422 br i1 %flag, label %if.then, label %if.else 423 424if.then: 425 %z = load volatile i32, ptr %y 426 %a = add i32 %z, 5 427 store volatile i32 %a, ptr %y, !tbaa !3 428 br label %if.end 429 430if.else: 431 %w = load volatile i32, ptr %y 432 %b = add i32 %w, 7 433 store volatile i32 %b, ptr %y, !tbaa !4 434 br label %if.end 435 436if.end: 437 ret i32 1 438} 439 440!0 = !{ !"an example type tree" } 441!1 = !{ !"int", !0 } 442!2 = !{ !"float", !0 } 443!3 = !{ !"const float", !2, i64 0 } 444!4 = !{ !"special float", !2, i64 1 } 445 446 447; The call should be commoned. 448define i32 @test13a(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) { 449; CHECK-LABEL: @test13a( 450; CHECK-NEXT: entry: 451; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 452; CHECK-NEXT: [[SV2:%.*]] = call i32 @bar(i32 [[X_Y]]) 453; CHECK-NEXT: ret i32 1 454; 455entry: 456 br i1 %flag, label %if.then, label %if.else 457 458if.then: 459 %sv1 = call i32 @bar(i32 %x) 460 br label %if.end 461 462if.else: 463 %sv2 = call i32 @bar(i32 %y) 464 br label %if.end 465 466if.end: 467 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ] 468 ret i32 1 469} 470declare i32 @bar(i32) 471 472 473; The load should be commoned. 474define i32 @test14(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, ptr %s) { 475; CHECK-LABEL: @test14( 476; CHECK-NEXT: entry: 477; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 1, i32 4 478; CHECK-NEXT: [[DOT2:%.*]] = select i1 [[FLAG]], i32 56, i32 57 479; CHECK-NEXT: [[DUMMY2:%.*]] = add i32 [[X:%.*]], [[DOT]] 480; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[S:%.*]], i32 0, i32 1 481; CHECK-NEXT: [[SV2:%.*]] = load i32, ptr [[GEPB]], align 4 482; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[SV2]], [[DOT2]] 483; CHECK-NEXT: ret i32 1 484; 485entry: 486 br i1 %flag, label %if.then, label %if.else 487 488if.then: 489 %dummy = add i32 %x, 1 490 %gepa = getelementptr inbounds %struct.anon, ptr %s, i32 0, i32 1 491 %sv1 = load i32, ptr %gepa 492 %cmp1 = icmp eq i32 %sv1, 56 493 br label %if.end 494 495if.else: 496 %dummy2 = add i32 %x, 4 497 %gepb = getelementptr inbounds %struct.anon, ptr %s, i32 0, i32 1 498 %sv2 = load i32, ptr %gepb 499 %cmp2 = icmp eq i32 %sv2, 57 500 call void @llvm.dbg.value(metadata i32 0, metadata !9, metadata !DIExpression()), !dbg !11 501 br label %if.end 502 503if.end: 504 %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ] 505 ret i32 1 506} 507 508declare void @llvm.dbg.value(metadata, metadata, metadata) 509!llvm.module.flags = !{!5, !6} 510!llvm.dbg.cu = !{!7} 511 512!5 = !{i32 2, !"Dwarf Version", i32 4} 513!6 = !{i32 2, !"Debug Info Version", i32 3} 514!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !10) 515!8 = distinct !DISubprogram(name: "foo", unit: !7) 516!9 = !DILocalVariable(name: "b", line: 1, arg: 2, scope: !8) 517!10 = !DIFile(filename: "a.c", directory: "a/b") 518!11 = !DILocation(line: 1, column: 14, scope: !8) 519 520 521; The load should not be commoned, as it will get separated from the GEP 522; instruction producing the address. 523define i32 @test15(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, ptr %s) { 524; CHECK-LABEL: @test15( 525; CHECK-NEXT: entry: 526; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 527; CHECK: if.then: 528; CHECK-NEXT: call void @bar(i32 1) 529; CHECK-NEXT: [[SV1:%.*]] = load i32, ptr [[S:%.*]], align 4 530; CHECK-NEXT: br label [[IF_END:%.*]] 531; CHECK: if.else: 532; CHECK-NEXT: call void @bar(i32 4) 533; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[S]], i32 0, i32 1 534; CHECK-NEXT: [[SV2:%.*]] = load i32, ptr [[GEPB]], align 4 535; CHECK-NEXT: br label [[IF_END]] 536; CHECK: if.end: 537; CHECK-NEXT: [[SV2_SINK:%.*]] = phi i32 [ [[SV2]], [[IF_ELSE]] ], [ [[SV1]], [[IF_THEN]] ] 538; CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ 57, [[IF_ELSE]] ], [ 56, [[IF_THEN]] ] 539; CHECK-NEXT: [[EXT2:%.*]] = zext i32 [[SV2_SINK]] to i64 540; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i64 [[EXT2]], [[DOTSINK]] 541; CHECK-NEXT: ret i32 1 542; 543entry: 544 br i1 %flag, label %if.then, label %if.else 545 546if.then: 547 call void @bar(i32 1) 548 %sv1 = load i32, ptr %s 549 %ext1 = zext i32 %sv1 to i64 550 %cmp1 = icmp eq i64 %ext1, 56 551 br label %if.end 552 553if.else: 554 call void @bar(i32 4) 555 %gepb = getelementptr inbounds %struct.anon, ptr %s, i32 0, i32 1 556 %sv2 = load i32, ptr %gepb 557 %ext2 = zext i32 %sv2 to i64 558 %cmp2 = icmp eq i64 %ext2, 57 559 br label %if.end 560 561if.end: 562 %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ] 563 ret i32 1 564} 565 566 567define zeroext i1 @test_crash(i1 zeroext %flag, ptr %i4, ptr %m, ptr %n) { 568; CHECK-LABEL: @test_crash( 569; CHECK-NEXT: entry: 570; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 571; CHECK: if.then: 572; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I4:%.*]], align 4 573; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], -1 574; CHECK-NEXT: br label [[IF_END:%.*]] 575; CHECK: if.else: 576; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[M:%.*]], align 4 577; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[N:%.*]], align 4 578; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP3]], [[TMP4]] 579; CHECK-NEXT: br label [[IF_END]] 580; CHECK: if.end: 581; CHECK-NEXT: [[TMP5_SINK:%.*]] = phi i32 [ [[TMP5]], [[IF_ELSE]] ], [ [[TMP2]], [[IF_THEN]] ] 582; CHECK-NEXT: store i32 [[TMP5_SINK]], ptr [[I4]], align 4 583; CHECK-NEXT: ret i1 true 584; 585entry: 586 br i1 %flag, label %if.then, label %if.else 587 588if.then: 589 %tmp1 = load i32, ptr %i4 590 %tmp2 = add i32 %tmp1, -1 591 store i32 %tmp2, ptr %i4 592 br label %if.end 593 594if.else: 595 %tmp3 = load i32, ptr %m 596 %tmp4 = load i32, ptr %n 597 %tmp5 = add i32 %tmp3, %tmp4 598 store i32 %tmp5, ptr %i4 599 br label %if.end 600 601if.end: 602 ret i1 true 603} 604 605; No checks for test_crash - just ensure it doesn't crash! 606 607define zeroext i1 @test16(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) { 608; CHECK-LABEL: @test16( 609; CHECK-NEXT: entry: 610; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 611; CHECK: if.then: 612; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 613; CHECK-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[CMP]] to i8 614; CHECK-NEXT: br label [[IF_END:%.*]] 615; CHECK: if.else: 616; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END]] 617; CHECK: if.then2: 618; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 619; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 620; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8 621; CHECK-NEXT: br label [[IF_END]] 622; CHECK: if.end: 623; CHECK-NEXT: [[OBEYS_0:%.*]] = phi i8 [ [[FROMBOOL1]], [[IF_THEN]] ], [ [[FROMBOOL3]], [[IF_THEN2]] ], [ 0, [[IF_ELSE]] ] 624; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[OBEYS_0]], 0 625; CHECK-NEXT: ret i1 [[TOBOOL4]] 626; 627entry: 628 br i1 %flag, label %if.then, label %if.else 629 630if.then: 631 %cmp = icmp uge i32 %blksA, %nblks 632 %frombool1 = zext i1 %cmp to i8 633 br label %if.end 634 635if.else: 636 br i1 %flag2, label %if.then2, label %if.end 637 638if.then2: 639 %add = add i32 %nblks, %blksB 640 %cmp2 = icmp ule i32 %add, %blksA 641 %frombool3 = zext i1 %cmp2 to i8 642 br label %if.end 643 644if.end: 645 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %if.else ] 646 %tobool4 = icmp ne i8 %obeys.0, 0 647 ret i1 %tobool4 648} 649 650 651define zeroext i1 @test16a(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks, ptr %p) { 652; CHECK-LABEL: @test16a( 653; CHECK-NEXT: entry: 654; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 655; CHECK: if.then: 656; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 657; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]] 658; CHECK: if.else: 659; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END:%.*]] 660; CHECK: if.then2: 661; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 662; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 663; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]] 664; CHECK: if.end.sink.split: 665; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 666; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8 667; CHECK-NEXT: store i8 [[FROMBOOL3]], ptr [[P:%.*]], align 1 668; CHECK-NEXT: br label [[IF_END]] 669; CHECK: if.end: 670; CHECK-NEXT: ret i1 true 671; 672entry: 673 br i1 %flag, label %if.then, label %if.else 674 675if.then: 676 %cmp = icmp uge i32 %blksA, %nblks 677 %frombool1 = zext i1 %cmp to i8 678 store i8 %frombool1, ptr %p 679 br label %if.end 680 681if.else: 682 br i1 %flag2, label %if.then2, label %if.end 683 684if.then2: 685 %add = add i32 %nblks, %blksB 686 %cmp2 = icmp ule i32 %add, %blksA 687 %frombool3 = zext i1 %cmp2 to i8 688 store i8 %frombool3, ptr %p 689 br label %if.end 690 691if.end: 692 ret i1 true 693} 694 695 696define zeroext i1 @test17(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 697; CHECK-LABEL: @test17( 698; CHECK-NEXT: entry: 699; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_END:%.*]] [ 700; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]] 701; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]] 702; CHECK-NEXT: ] 703; CHECK: if.then: 704; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 705; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]] 706; CHECK: if.then2: 707; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 708; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 709; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]] 710; CHECK: if.end.sink.split: 711; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 712; CHECK-NEXT: [[FROMBOOL3:%.*]] = call i8 @i1toi8(i1 [[CMP2_SINK]]) 713; CHECK-NEXT: br label [[IF_END]] 714; CHECK: if.end: 715; CHECK-NEXT: [[OBEYS_0:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[FROMBOOL3]], [[IF_END_SINK_SPLIT]] ] 716; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[OBEYS_0]], 0 717; CHECK-NEXT: ret i1 [[TOBOOL4]] 718; 719entry: 720 switch i32 %flag, label %if.end [ 721 i32 0, label %if.then 722 i32 1, label %if.then2 723 ] 724 725if.then: 726 %cmp = icmp uge i32 %blksA, %nblks 727 %frombool1 = call i8 @i1toi8(i1 %cmp) 728 br label %if.end 729 730if.then2: 731 %add = add i32 %nblks, %blksB 732 %cmp2 = icmp ule i32 %add, %blksA 733 %frombool3 = call i8 @i1toi8(i1 %cmp2) 734 br label %if.end 735 736if.end: 737 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %entry ] 738 %tobool4 = icmp ne i8 %obeys.0, 0 739 ret i1 %tobool4 740} 741declare i8 @i1toi8(i1) 742 743 744 745 746 747define zeroext i1 @test18(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 748; CHECK-LABEL: @test18( 749; CHECK-NEXT: entry: 750; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_THEN3:%.*]] [ 751; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]] 752; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]] 753; CHECK-NEXT: ] 754; CHECK: if.then: 755; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 756; CHECK-NEXT: br label [[IF_END:%.*]] 757; CHECK: if.then2: 758; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 759; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 760; CHECK-NEXT: br label [[IF_END]] 761; CHECK: if.then3: 762; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[NBLKS]], [[BLKSA]] 763; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[ADD2]], [[BLKSA]] 764; CHECK-NEXT: br label [[IF_END]] 765; CHECK: if.end: 766; CHECK-NEXT: [[CMP3_SINK:%.*]] = phi i1 [ [[CMP3]], [[IF_THEN3]] ], [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 767; CHECK-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[CMP3_SINK]] to i8 768; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL4]], 0 769; CHECK-NEXT: ret i1 [[TOBOOL4]] 770; 771entry: 772 switch i32 %flag, label %if.then3 [ 773 i32 0, label %if.then 774 i32 1, label %if.then2 775 ] 776 777if.then: 778 %cmp = icmp uge i32 %blksA, %nblks 779 %frombool1 = zext i1 %cmp to i8 780 br label %if.end 781 782if.then2: 783 %add = add i32 %nblks, %blksB 784 %cmp2 = icmp ule i32 %add, %blksA 785 %frombool3 = zext i1 %cmp2 to i8 786 br label %if.end 787 788if.then3: 789 %add2 = add i32 %nblks, %blksA 790 %cmp3 = icmp ule i32 %add2, %blksA 791 %frombool4 = zext i1 %cmp3 to i8 792 br label %if.end 793 794if.end: 795 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ %frombool4, %if.then3 ] 796 %tobool4 = icmp ne i8 %obeys.0, 0 797 ret i1 %tobool4 798} 799 800 801define i32 @test_pr30188(i1 zeroext %flag, i32 %x) { 802; CHECK-LABEL: @test_pr30188( 803; CHECK-NEXT: entry: 804; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 805; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 806; CHECK-NEXT: [[Y_Z:%.*]] = select i1 [[FLAG:%.*]], ptr [[Y]], ptr [[Z]] 807; CHECK-NEXT: store i32 [[X:%.*]], ptr [[Y_Z]], align 4 808; CHECK-NEXT: ret i32 1 809; 810entry: 811 %y = alloca i32 812 %z = alloca i32 813 br i1 %flag, label %if.then, label %if.else 814 815if.then: 816 store i32 %x, ptr %y 817 br label %if.end 818 819if.else: 820 store i32 %x, ptr %z 821 br label %if.end 822 823if.end: 824 ret i32 1 825} 826 827 828define i32 @test_pr30188a(i1 zeroext %flag, i32 %x) { 829; CHECK-LABEL: @test_pr30188a( 830; CHECK-NEXT: entry: 831; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 832; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 833; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 834; CHECK: if.then: 835; CHECK-NEXT: call void @g() 836; CHECK-NEXT: br label [[IF_END]] 837; CHECK: if.end: 838; CHECK-NEXT: [[Z_SINK:%.*]] = phi ptr [ [[Y]], [[IF_THEN]] ], [ [[Z]], [[ENTRY:%.*]] ] 839; CHECK-NEXT: [[THREE:%.*]] = load i32, ptr [[Z_SINK]], align 4 840; CHECK-NEXT: [[FOUR:%.*]] = add i32 [[THREE]], 2 841; CHECK-NEXT: store i32 [[FOUR]], ptr [[Y]], align 4 842; CHECK-NEXT: ret i32 1 843; 844entry: 845 %y = alloca i32 846 %z = alloca i32 847 br i1 %flag, label %if.then, label %if.else 848 849if.then: 850 call void @g() 851 %one = load i32, ptr %y 852 %two = add i32 %one, 2 853 store i32 %two, ptr %y 854 br label %if.end 855 856if.else: 857 %three = load i32, ptr %z 858 %four = add i32 %three, 2 859 store i32 %four, ptr %y 860 br label %if.end 861 862if.end: 863 ret i32 1 864} 865 866 867; The phi is confusing - both add instructions are used by it, but 868; not on their respective unconditional arcs. It should not be 869; optimized. 870define void @test_pr30292(i1 %cond, i1 %cond2, i32 %a, i32 %b) { 871; CHECK-LABEL: @test_pr30292( 872; CHECK-NEXT: entry: 873; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], 1 874; CHECK-NEXT: br label [[SUCC:%.*]] 875; CHECK: two: 876; CHECK-NEXT: call void @g() 877; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[A]], 1 878; CHECK-NEXT: br label [[SUCC]] 879; CHECK: succ: 880; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ], [ [[ADD2]], [[TWO:%.*]] ] 881; CHECK-NEXT: br i1 [[COND:%.*]], label [[TWO]], label [[SUCC]] 882; 883entry: 884 %add1 = add i32 %a, 1 885 br label %succ 886 887one: 888 br i1 %cond, label %two, label %succ 889 890two: 891 call void @g() 892 %add2 = add i32 %a, 1 893 br label %succ 894 895succ: 896 %p = phi i32 [ 0, %entry ], [ %add1, %one ], [ %add2, %two ] 897 br label %one 898} 899declare void @g() 900 901 902define zeroext i1 @test_pr30244(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) { 903; CHECK-LABEL: @test_pr30244( 904; CHECK-NEXT: entry: 905; CHECK-NEXT: [[P:%.*]] = alloca i8, align 1 906; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 907; CHECK: if.then: 908; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 909; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]] 910; CHECK: if.else: 911; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END:%.*]] 912; CHECK: if.then2: 913; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 914; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 915; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]] 916; CHECK: if.end.sink.split: 917; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 918; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8 919; CHECK-NEXT: store i8 [[FROMBOOL3]], ptr [[P]], align 1 920; CHECK-NEXT: br label [[IF_END]] 921; CHECK: if.end: 922; CHECK-NEXT: ret i1 true 923; 924entry: 925 %p = alloca i8 926 br i1 %flag, label %if.then, label %if.else 927 928if.then: 929 %cmp = icmp uge i32 %blksA, %nblks 930 %frombool1 = zext i1 %cmp to i8 931 store i8 %frombool1, ptr %p 932 br label %if.end 933 934if.else: 935 br i1 %flag2, label %if.then2, label %if.end 936 937if.then2: 938 %add = add i32 %nblks, %blksB 939 %cmp2 = icmp ule i32 %add, %blksA 940 %frombool3 = zext i1 %cmp2 to i8 941 store i8 %frombool3, ptr %p 942 br label %if.end 943 944if.end: 945 ret i1 true 946} 947 948 949define i32 @test_pr30373a(i1 zeroext %flag, i32 %x, i32 %y) { 950; CHECK-LABEL: @test_pr30373a( 951; CHECK-NEXT: entry: 952; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 953; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0]] 954; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]] 955; CHECK-NEXT: [[Z1:%.*]] = lshr i32 [[Y1]], 8 956; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Z1]] 957; CHECK-NEXT: ret i32 [[RET]] 958; 959entry: 960 br i1 %flag, label %if.then, label %if.else 961 962if.then: 963 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone 964 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone 965 %z0 = lshr i32 %y0, 8 966 br label %if.end 967 968if.else: 969 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone 970 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone 971 %z1 = lshr exact i32 %y1, 8 972 br label %if.end 973 974if.end: 975 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] 976 %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ] 977 %ret = add i32 %xx, %yy 978 ret i32 %ret 979} 980 981 982define i32 @test_pr30373b(i1 zeroext %flag, i32 %x, i32 %y) { 983; CHECK-LABEL: @test_pr30373b( 984; CHECK-NEXT: entry: 985; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 986; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0]] 987; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]] 988; CHECK-NEXT: [[Z1:%.*]] = lshr i32 [[Y1]], 8 989; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Z1]] 990; CHECK-NEXT: ret i32 [[RET]] 991; 992entry: 993 br i1 %flag, label %if.then, label %if.else 994 995if.then: 996 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone 997 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone 998 %z0 = lshr exact i32 %y0, 8 999 br label %if.end 1000 1001if.else: 1002 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone 1003 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone 1004 %z1 = lshr i32 %y1, 8 1005 br label %if.end 1006 1007if.end: 1008 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] 1009 %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ] 1010 %ret = add i32 %xx, %yy 1011 ret i32 %ret 1012} 1013 1014 1015 1016; FIXME: Should turn into select 1017define float @allow_intrinsic_remove_constant(i1 zeroext %flag, float %w, float %x, float %y) { 1018; CHECK-LABEL: @allow_intrinsic_remove_constant( 1019; CHECK-NEXT: entry: 1020; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1021; CHECK: if.then: 1022; CHECK-NEXT: [[DUMMY:%.*]] = fadd float [[W:%.*]], 4.000000e+00 1023; CHECK-NEXT: [[SV1:%.*]] = call float @llvm.fma.f32(float [[DUMMY]], float 2.000000e+00, float 1.000000e+00) 1024; CHECK-NEXT: br label [[IF_END:%.*]] 1025; CHECK: if.else: 1026; CHECK-NEXT: [[DUMMY1:%.*]] = fadd float [[W]], 8.000000e+00 1027; CHECK-NEXT: [[SV2:%.*]] = call float @llvm.fma.f32(float 2.000000e+00, float [[DUMMY1]], float 1.000000e+00) 1028; CHECK-NEXT: br label [[IF_END]] 1029; CHECK: if.end: 1030; CHECK-NEXT: [[P:%.*]] = phi float [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 1031; CHECK-NEXT: ret float [[P]] 1032; 1033entry: 1034 br i1 %flag, label %if.then, label %if.else 1035 1036if.then: 1037 %dummy = fadd float %w, 4.0 1038 %sv1 = call float @llvm.fma.f32(float %dummy, float 2.0, float 1.0) 1039 br label %if.end 1040 1041if.else: 1042 %dummy1 = fadd float %w, 8.0 1043 %sv2 = call float @llvm.fma.f32(float 2.0, float %dummy1, float 1.0) 1044 br label %if.end 1045 1046if.end: 1047 %p = phi float [ %sv1, %if.then ], [ %sv2, %if.else ] 1048 ret float %p 1049} 1050 1051declare float @llvm.fma.f32(float, float, float) 1052 1053define i32 @no_remove_constant_immarg(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) { 1054; CHECK-LABEL: @no_remove_constant_immarg( 1055; CHECK-NEXT: entry: 1056; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1057; CHECK: if.then: 1058; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5 1059; CHECK-NEXT: [[SV1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true) 1060; CHECK-NEXT: br label [[IF_END:%.*]] 1061; CHECK: if.else: 1062; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6 1063; CHECK-NEXT: [[SV2:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X]], i1 false) 1064; CHECK-NEXT: br label [[IF_END]] 1065; CHECK: if.end: 1066; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 1067; CHECK-NEXT: ret i32 1 1068; 1069entry: 1070 br i1 %flag, label %if.then, label %if.else 1071 1072if.then: 1073 %dummy = add i32 %w, 5 1074 %sv1 = call i32 @llvm.ctlz.i32(i32 %x, i1 true) 1075 br label %if.end 1076 1077if.else: 1078 %dummy1 = add i32 %w, 6 1079 %sv2 = call i32 @llvm.ctlz.i32(i32 %x, i1 false) 1080 br label %if.end 1081 1082if.end: 1083 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ] 1084 ret i32 1 1085} 1086 1087declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture readonly, i64, i1) 1088 1089; Make sure a memcpy size isn't replaced with a variable 1090define void @no_replace_memcpy_size(i1 zeroext %flag, ptr addrspace(1) %dst, ptr addrspace(1) %src) { 1091; CHECK-LABEL: @no_replace_memcpy_size( 1092; CHECK-NEXT: entry: 1093; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1094; CHECK: if.then: 1095; CHECK-NEXT: call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) [[DST:%.*]], ptr addrspace(1) [[SRC:%.*]], i64 1024, i1 false) 1096; CHECK-NEXT: br label [[IF_END:%.*]] 1097; CHECK: if.else: 1098; CHECK-NEXT: call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) [[DST]], ptr addrspace(1) [[SRC]], i64 4096, i1 false) 1099; CHECK-NEXT: br label [[IF_END]] 1100; CHECK: if.end: 1101; CHECK-NEXT: ret void 1102; 1103entry: 1104 br i1 %flag, label %if.then, label %if.else 1105 1106if.then: 1107 call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %dst, ptr addrspace(1) %src, i64 1024, i1 false) 1108 br label %if.end 1109 1110if.else: 1111 call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %dst, ptr addrspace(1) %src, i64 4096, i1 false) 1112 br label %if.end 1113 1114if.end: 1115 ret void 1116} 1117 1118declare void @llvm.memmove.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture readonly, i64, i1) 1119 1120; Make sure a memmove size isn't replaced with a variable 1121define void @no_replace_memmove_size(i1 zeroext %flag, ptr addrspace(1) %dst, ptr addrspace(1) %src) { 1122; CHECK-LABEL: @no_replace_memmove_size( 1123; CHECK-NEXT: entry: 1124; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1125; CHECK: if.then: 1126; CHECK-NEXT: call void @llvm.memmove.p1.p1.i64(ptr addrspace(1) [[DST:%.*]], ptr addrspace(1) [[SRC:%.*]], i64 1024, i1 false) 1127; CHECK-NEXT: br label [[IF_END:%.*]] 1128; CHECK: if.else: 1129; CHECK-NEXT: call void @llvm.memmove.p1.p1.i64(ptr addrspace(1) [[DST]], ptr addrspace(1) [[SRC]], i64 4096, i1 false) 1130; CHECK-NEXT: br label [[IF_END]] 1131; CHECK: if.end: 1132; CHECK-NEXT: ret void 1133; 1134entry: 1135 br i1 %flag, label %if.then, label %if.else 1136 1137if.then: 1138 call void @llvm.memmove.p1.p1.i64(ptr addrspace(1) %dst, ptr addrspace(1) %src, i64 1024, i1 false) 1139 br label %if.end 1140 1141if.else: 1142 call void @llvm.memmove.p1.p1.i64(ptr addrspace(1) %dst, ptr addrspace(1) %src, i64 4096, i1 false) 1143 br label %if.end 1144 1145if.end: 1146 ret void 1147} 1148 1149declare void @llvm.memset.p1.i64(ptr addrspace(1) nocapture, i8, i64, i1) 1150 1151; Make sure a memset size isn't replaced with a variable 1152define void @no_replace_memset_size(i1 zeroext %flag, ptr addrspace(1) %dst) { 1153; CHECK-LABEL: @no_replace_memset_size( 1154; CHECK-NEXT: entry: 1155; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1156; CHECK: if.then: 1157; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) [[DST:%.*]], i8 0, i64 1024, i1 false) 1158; CHECK-NEXT: br label [[IF_END:%.*]] 1159; CHECK: if.else: 1160; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) [[DST]], i8 0, i64 4096, i1 false) 1161; CHECK-NEXT: br label [[IF_END]] 1162; CHECK: if.end: 1163; CHECK-NEXT: ret void 1164; 1165entry: 1166 br i1 %flag, label %if.then, label %if.else 1167 1168if.then: 1169 call void @llvm.memset.p1.i64(ptr addrspace(1) %dst, i8 0, i64 1024, i1 false) 1170 br label %if.end 1171 1172if.else: 1173 call void @llvm.memset.p1.i64(ptr addrspace(1) %dst, i8 0, i64 4096, i1 false) 1174 br label %if.end 1175 1176if.end: 1177 ret void 1178} 1179 1180; Check that simplifycfg doesn't sink and merge inline-asm instructions. 1181 1182define i32 @test_inline_asm1(i32 %c, i32 %r6) { 1183; CHECK-LABEL: @test_inline_asm1( 1184; CHECK-NEXT: entry: 1185; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C:%.*]], 0 1186; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] 1187; CHECK: if.then: 1188; CHECK-NEXT: [[TMP0:%.*]] = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 [[R6:%.*]], i32 8) 1189; CHECK-NEXT: br label [[IF_END:%.*]] 1190; CHECK: if.else: 1191; CHECK-NEXT: [[TMP1:%.*]] = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 [[R6]], i32 6) 1192; CHECK-NEXT: br label [[IF_END]] 1193; CHECK: if.end: 1194; CHECK-NEXT: [[R6_ADDR_0:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] 1195; CHECK-NEXT: ret i32 [[R6_ADDR_0]] 1196; 1197entry: 1198 %tobool = icmp eq i32 %c, 0 1199 br i1 %tobool, label %if.else, label %if.then 1200 1201if.then: 1202 %0 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8) 1203 br label %if.end 1204 1205if.else: 1206 %1 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6) 1207 br label %if.end 1208 1209if.end: 1210 %r6.addr.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ] 1211 ret i32 %r6.addr.0 1212} 1213 1214 1215declare i32 @call_target() 1216 1217define void @test_operand_bundles(i1 %cond, ptr %ptr) { 1218; CHECK-LABEL: @test_operand_bundles( 1219; CHECK-NEXT: entry: 1220; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 1221; CHECK: left: 1222; CHECK-NEXT: [[VAL0:%.*]] = call i32 @call_target() [ "deopt"(i32 10) ] 1223; CHECK-NEXT: br label [[MERGE:%.*]] 1224; CHECK: right: 1225; CHECK-NEXT: [[VAL1:%.*]] = call i32 @call_target() [ "deopt"(i32 20) ] 1226; CHECK-NEXT: br label [[MERGE]] 1227; CHECK: merge: 1228; CHECK-NEXT: [[VAL1_SINK:%.*]] = phi i32 [ [[VAL1]], [[RIGHT]] ], [ [[VAL0]], [[LEFT]] ] 1229; CHECK-NEXT: store i32 [[VAL1_SINK]], ptr [[PTR:%.*]], align 4 1230; CHECK-NEXT: ret void 1231; 1232entry: 1233 br i1 %cond, label %left, label %right 1234 1235left: 1236 %val0 = call i32 @call_target() [ "deopt"(i32 10) ] 1237 store i32 %val0, ptr %ptr 1238 br label %merge 1239 1240right: 1241 %val1 = call i32 @call_target() [ "deopt"(i32 20) ] 1242 store i32 %val1, ptr %ptr 1243 br label %merge 1244 1245merge: 1246 ret void 1247} 1248 1249 1250%TP = type {i32, i32} 1251 1252define i32 @test_insertvalue(i1 zeroext %flag, %TP %P) { 1253; CHECK-LABEL: @test_insertvalue( 1254; CHECK-NEXT: entry: 1255; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 0, i32 1 1256; CHECK-NEXT: [[I2:%.*]] = insertvalue [[TP:%.*]] [[P:%.*]], i32 [[DOT]], 0 1257; CHECK-NEXT: ret i32 1 1258; 1259entry: 1260 br i1 %flag, label %if.then, label %if.else 1261 1262if.then: 1263 %i1 = insertvalue %TP %P, i32 0, 0 1264 br label %if.end 1265 1266if.else: 1267 %i2 = insertvalue %TP %P, i32 1, 0 1268 br label %if.end 1269 1270if.end: 1271 %i = phi %TP [%i1, %if.then], [%i2, %if.else] 1272 ret i32 1 1273} 1274 1275 1276 1277declare void @baz(i32) 1278 1279define void @test_sink_void_calls(i32 %x) { 1280; CHECK-LABEL: @test_sink_void_calls( 1281; CHECK-NEXT: entry: 1282; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [ 1283; CHECK-NEXT: i32 0, label [[RETURN:%.*]] 1284; CHECK-NEXT: i32 1, label [[BB1:%.*]] 1285; CHECK-NEXT: i32 2, label [[BB2:%.*]] 1286; CHECK-NEXT: i32 3, label [[BB3:%.*]] 1287; CHECK-NEXT: i32 4, label [[BB4:%.*]] 1288; CHECK-NEXT: ] 1289; CHECK: bb1: 1290; CHECK-NEXT: br label [[RETURN]] 1291; CHECK: bb2: 1292; CHECK-NEXT: br label [[RETURN]] 1293; CHECK: bb3: 1294; CHECK-NEXT: br label [[RETURN]] 1295; CHECK: bb4: 1296; CHECK-NEXT: br label [[RETURN]] 1297; CHECK: default: 1298; CHECK-NEXT: unreachable 1299; CHECK: return: 1300; CHECK-NEXT: [[DOTSINK:%.*]] = phi i32 [ 90, [[BB4]] ], [ 78, [[BB3]] ], [ 56, [[BB2]] ], [ 34, [[BB1]] ], [ 12, [[ENTRY:%.*]] ] 1301; CHECK-NEXT: call void @baz(i32 [[DOTSINK]]) 1302; CHECK-NEXT: ret void 1303; 1304entry: 1305 switch i32 %x, label %default [ 1306 i32 0, label %bb0 1307 i32 1, label %bb1 1308 i32 2, label %bb2 1309 i32 3, label %bb3 1310 i32 4, label %bb4 1311 ] 1312bb0: 1313 call void @baz(i32 12) 1314 br label %return 1315bb1: 1316 call void @baz(i32 34) 1317 br label %return 1318bb2: 1319 call void @baz(i32 56) 1320 br label %return 1321bb3: 1322 call void @baz(i32 78) 1323 br label %return 1324bb4: 1325 call void @baz(i32 90) 1326 br label %return 1327default: 1328 unreachable 1329return: 1330 ret void 1331 1332; Check that the calls get sunk to the return block. 1333; We would previously not sink calls without uses, see PR41259. 1334} 1335 1336define i32 @test_not_sink_lifetime_marker(i1 zeroext %flag, i32 %x) { 1337; CHECK-LABEL: @test_not_sink_lifetime_marker( 1338; CHECK-NEXT: entry: 1339; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 1340; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 1341; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1342; CHECK: if.then: 1343; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[Y]]) 1344; CHECK-NEXT: br label [[IF_END:%.*]] 1345; CHECK: if.else: 1346; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[Z]]) 1347; CHECK-NEXT: br label [[IF_END]] 1348; CHECK: if.end: 1349; CHECK-NEXT: ret i32 1 1350; 1351entry: 1352 %y = alloca i32 1353 %z = alloca i32 1354 br i1 %flag, label %if.then, label %if.else 1355 1356if.then: 1357 call void @llvm.lifetime.end.p0(i64 4, ptr %y) 1358 br label %if.end 1359 1360if.else: 1361 call void @llvm.lifetime.end.p0(i64 4, ptr %z) 1362 br label %if.end 1363 1364if.end: 1365 ret i32 1 1366} 1367 1368define void @direct_caller(i1 %c) { 1369; CHECK-LABEL: @direct_caller( 1370; CHECK-NEXT: br i1 [[C:%.*]], label [[CALL_FOO:%.*]], label [[CALL_BAR:%.*]] 1371; CHECK: call_foo: 1372; CHECK-NEXT: call void @direct_callee() 1373; CHECK-NEXT: br label [[END:%.*]] 1374; CHECK: call_bar: 1375; CHECK-NEXT: call void @direct_callee2() 1376; CHECK-NEXT: br label [[END]] 1377; CHECK: end: 1378; CHECK-NEXT: ret void 1379; 1380 br i1 %c, label %call_foo, label %call_bar 1381 1382call_foo: 1383 call void @direct_callee() 1384 br label %end 1385 1386call_bar: 1387 call void @direct_callee2() 1388 br label %end 1389 1390end: 1391 ret void 1392} 1393 1394define void @indirect_caller(i1 %c, i32 %v, ptr %foo, ptr %bar) { 1395; CHECK-LABEL: @indirect_caller( 1396; CHECK-NEXT: end: 1397; CHECK-NEXT: [[FOO_BAR:%.*]] = select i1 [[C:%.*]], ptr [[FOO:%.*]], ptr [[BAR:%.*]] 1398; CHECK-NEXT: tail call void [[FOO_BAR]](i32 [[V:%.*]]) 1399; CHECK-NEXT: ret void 1400; 1401 br i1 %c, label %call_foo, label %call_bar 1402 1403call_foo: 1404 tail call void %foo(i32 %v) 1405 br label %end 1406 1407call_bar: 1408 tail call void %bar(i32 %v) 1409 br label %end 1410 1411end: 1412 ret void 1413} 1414 1415define void @maybe_indirect_caller(ptr %fun) { 1416; CHECK-LABEL: @maybe_indirect_caller( 1417; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[FUN:%.*]], @direct_callee 1418; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE_DIRECT_TARG:%.*]], label [[IF_FALSE_ORIG_INDIRECT:%.*]] 1419; CHECK: if.true.direct_targ: 1420; CHECK-NEXT: tail call void @direct_callee() 1421; CHECK-NEXT: br label [[IF_END_ICP:%.*]] 1422; CHECK: if.false.orig_indirect: 1423; CHECK-NEXT: tail call void [[FUN]]() 1424; CHECK-NEXT: br label [[IF_END_ICP]] 1425; CHECK: if.end.icp: 1426; CHECK-NEXT: ret void 1427; 1428 %c = icmp eq ptr %fun, @direct_callee 1429 br i1 %c, label %if.true.direct_targ, label %if.false.orig_indirect 1430 1431if.true.direct_targ: 1432 tail call void @direct_callee() 1433 br label %if.end.icp 1434 1435if.false.orig_indirect: 1436 tail call void %fun() 1437 br label %if.end.icp 1438 1439if.end.icp: 1440 ret void 1441} 1442define void @maybe_indirect_caller2(ptr %fun) { 1443; CHECK-LABEL: @maybe_indirect_caller2( 1444; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[FUN:%.*]], @direct_callee 1445; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE_DIRECT_TARG:%.*]], label [[IF_FALSE_ORIG_INDIRECT:%.*]] 1446; CHECK: if.false.orig_indirect: 1447; CHECK-NEXT: tail call void [[FUN]]() 1448; CHECK-NEXT: br label [[IF_END_ICP:%.*]] 1449; CHECK: if.true.direct_targ: 1450; CHECK-NEXT: tail call void @direct_callee() 1451; CHECK-NEXT: br label [[IF_END_ICP]] 1452; CHECK: if.end.icp: 1453; CHECK-NEXT: ret void 1454; 1455 %c = icmp eq ptr %fun, @direct_callee 1456 br i1 %c, label %if.true.direct_targ, label %if.false.orig_indirect 1457 1458if.false.orig_indirect: 1459 tail call void %fun() 1460 br label %if.end.icp 1461 1462if.true.direct_targ: 1463 tail call void @direct_callee() 1464 br label %if.end.icp 1465 1466if.end.icp: 1467 ret void 1468} 1469declare void @direct_callee() 1470declare void @direct_callee2() 1471declare void @direct_callee3() 1472 1473declare void @llvm.lifetime.start.p0(i64, ptr nocapture) 1474declare void @llvm.lifetime.end.p0(i64, ptr nocapture) 1475 1476define void @creating_too_many_phis(i1 %cond, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) { 1477; CHECK-LABEL: @creating_too_many_phis( 1478; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 1479; CHECK: bb0: 1480; CHECK-NEXT: [[V0:%.*]] = add i32 [[A:%.*]], [[B:%.*]] 1481; CHECK-NEXT: [[V1:%.*]] = add i32 [[V0]], [[C:%.*]] 1482; CHECK-NEXT: [[V2:%.*]] = add i32 [[D:%.*]], [[E:%.*]] 1483; CHECK-NEXT: [[R3:%.*]] = add i32 [[V1]], [[V2]] 1484; CHECK-NEXT: br label [[END:%.*]] 1485; CHECK: bb1: 1486; CHECK-NEXT: [[V4:%.*]] = add i32 [[A]], [[B]] 1487; CHECK-NEXT: [[V5:%.*]] = add i32 [[V4]], [[C]] 1488; CHECK-NEXT: [[V6:%.*]] = add i32 [[G:%.*]], [[H:%.*]] 1489; CHECK-NEXT: [[R7:%.*]] = add i32 [[V5]], [[V6]] 1490; CHECK-NEXT: br label [[END]] 1491; CHECK: end: 1492; CHECK-NEXT: [[R7_SINK:%.*]] = phi i32 [ [[R7]], [[BB1]] ], [ [[R3]], [[BB0]] ] 1493; CHECK-NEXT: call void @use32(i32 [[R7_SINK]]) 1494; CHECK-NEXT: ret void 1495; 1496 br i1 %cond, label %bb0, label %bb1 1497 1498bb0: 1499 %v0 = add i32 %a, %b 1500 %v1 = add i32 %v0, %c 1501 %v2 = add i32 %d, %e 1502 %r3 = add i32 %v1, %v2 1503 call void @use32(i32 %r3) 1504 br label %end 1505 1506bb1: 1507 %v4 = add i32 %a, %b 1508 %v5 = add i32 %v4, %c 1509 %v6 = add i32 %g, %h 1510 %r7 = add i32 %v5, %v6 1511 call void @use32(i32 %r7) 1512 br label %end 1513 1514end: 1515 ret void 1516} 1517declare void @use32(i32) 1518 1519define void @multiple_cond_preds(i1 %c0, i1 %c1, i1 %c2) { 1520; CHECK-LABEL: @multiple_cond_preds( 1521; CHECK-NEXT: dispatch0: 1522; CHECK-NEXT: br i1 [[C0:%.*]], label [[DISPATCH1:%.*]], label [[DISPATCH2:%.*]] 1523; CHECK: dispatch1: 1524; CHECK-NEXT: call void @direct_callee2() 1525; CHECK-NEXT: br i1 [[C1:%.*]], label [[END_SINK_SPLIT:%.*]], label [[END:%.*]] 1526; CHECK: dispatch2: 1527; CHECK-NEXT: call void @direct_callee3() 1528; CHECK-NEXT: br i1 [[C2:%.*]], label [[END_SINK_SPLIT]], label [[END]] 1529; CHECK: end.sink.split: 1530; CHECK-NEXT: call void @direct_callee() 1531; CHECK-NEXT: br label [[END]] 1532; CHECK: end: 1533; CHECK-NEXT: ret void 1534; 1535dispatch0: 1536 br i1 %c0, label %dispatch1, label %dispatch2 1537 1538dispatch1: 1539 call void @direct_callee2() 1540 br i1 %c1, label %uncond_pred0, label %end 1541 1542dispatch2: 1543 call void @direct_callee3() 1544 br i1 %c2, label %uncond_pred1, label %end 1545 1546uncond_pred0: 1547 call void @direct_callee() 1548 br label %end 1549 1550uncond_pred1: 1551 call void @direct_callee() 1552 br label %end 1553 1554end: 1555 ret void 1556} 1557 1558define void @nontemporal(ptr %ptr, i1 %cond) { 1559; CHECK-LABEL: @nontemporal( 1560; CHECK-NEXT: entry: 1561; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8, !nontemporal [[META7:![0-9]+]] 1562; CHECK-NEXT: ret void 1563; 1564entry: 1565 br i1 %cond, label %if.then, label %if.else 1566 1567if.then: 1568 store i64 0, ptr %ptr, align 8, !nontemporal !12 1569 br label %if.end 1570 1571if.else: 1572 store i64 0, ptr %ptr, align 8, !nontemporal !12 1573 br label %if.end 1574 1575if.end: 1576 ret void 1577} 1578 1579define void @nontemporal_mismatch(ptr %ptr, i1 %cond) { 1580; CHECK-LABEL: @nontemporal_mismatch( 1581; CHECK-NEXT: entry: 1582; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8 1583; CHECK-NEXT: ret void 1584; 1585entry: 1586 br i1 %cond, label %if.then, label %if.else 1587 1588if.then: 1589 store i64 0, ptr %ptr, align 8, !nontemporal !12 1590 br label %if.end 1591 1592if.else: 1593 store i64 0, ptr %ptr, align 8 1594 br label %if.end 1595 1596if.end: 1597 ret void 1598} 1599 1600define void @loop_use_in_different_bb(i32 %n) { 1601; CHECK-LABEL: @loop_use_in_different_bb( 1602; CHECK-NEXT: entry: 1603; CHECK-NEXT: [[ADD:%.*]] = add i32 [[N:%.*]], 1 1604; CHECK-NEXT: br label [[FOR_COND:%.*]] 1605; CHECK: for.cond: 1606; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ] 1607; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV]], [[ADD]] 1608; CHECK-NEXT: br i1 [[EXITCOND]], label [[RETURN:%.*]], label [[FOR_BODY]] 1609; CHECK: for.body: 1610; CHECK-NEXT: [[INC]] = add i32 [[IV]], 1 1611; CHECK-NEXT: br label [[FOR_COND]] 1612; CHECK: return: 1613; CHECK-NEXT: ret void 1614; 1615entry: 1616 %add = add i32 %n, 1 1617 br label %for.cond 1618 1619for.cond: 1620 %iv = phi i32 [ 0, %entry ], [ %inc, %for.body ] 1621 %exitcond = icmp eq i32 %iv, %add 1622 br i1 %exitcond, label %return, label %for.body 1623 1624for.body: 1625 %inc = add i32 %iv, 1 1626 br label %for.cond 1627 1628return: 1629 ret void 1630} 1631 1632define void @loop_use_in_different_bb_phi(i32 %n) { 1633; CHECK-LABEL: @loop_use_in_different_bb_phi( 1634; CHECK-NEXT: entry: 1635; CHECK-NEXT: [[ADD:%.*]] = add i32 [[N:%.*]], 1 1636; CHECK-NEXT: br label [[FOR_COND:%.*]] 1637; CHECK: for.cond: 1638; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ] 1639; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV]], 42 1640; CHECK-NEXT: br i1 [[EXITCOND]], label [[RETURN:%.*]], label [[FOR_BODY]] 1641; CHECK: for.body: 1642; CHECK-NEXT: [[DUMMY:%.*]] = phi i32 [ [[ADD]], [[FOR_COND]] ] 1643; CHECK-NEXT: [[INC]] = add i32 [[IV]], 1 1644; CHECK-NEXT: br label [[FOR_COND]] 1645; CHECK: return: 1646; CHECK-NEXT: ret void 1647; 1648entry: 1649 %add = add i32 %n, 1 1650 br label %for.cond 1651 1652for.cond: 1653 %iv = phi i32 [ 0, %entry ], [ %inc, %for.body ] 1654 %exitcond = icmp eq i32 %iv, 42 1655 br i1 %exitcond, label %return, label %for.body 1656 1657for.body: 1658 %dummy = phi i32 [ %add, %for.cond ] 1659 %inc = add i32 %iv, 1 1660 br label %for.cond 1661 1662return: 1663 ret void 1664} 1665 1666define void @loop_use_in_wrong_phi_operand(i32 %n) { 1667; CHECK-LABEL: @loop_use_in_wrong_phi_operand( 1668; CHECK-NEXT: entry: 1669; CHECK-NEXT: [[ADD:%.*]] = add i32 [[N:%.*]], 1 1670; CHECK-NEXT: br label [[FOR_COND:%.*]] 1671; CHECK: for.cond: 1672; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD]], [[FOR_BODY:%.*]] ] 1673; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV]], 42 1674; CHECK-NEXT: br i1 [[EXITCOND]], label [[RETURN:%.*]], label [[FOR_BODY]] 1675; CHECK: for.body: 1676; CHECK-NEXT: [[INC:%.*]] = add i32 [[IV]], 1 1677; CHECK-NEXT: br label [[FOR_COND]] 1678; CHECK: return: 1679; CHECK-NEXT: ret void 1680; 1681entry: 1682 %add = add i32 %n, 1 1683 br label %for.cond 1684 1685for.cond: 1686 %iv = phi i32 [ 0, %entry ], [ %add, %for.body ] 1687 %exitcond = icmp eq i32 %iv, 42 1688 br i1 %exitcond, label %return, label %for.body 1689 1690for.body: 1691 %inc = add i32 %iv, 1 1692 br label %for.cond 1693 1694return: 1695 ret void 1696} 1697 1698define ptr @multi_use_in_phi(i1 %cond, ptr %p, i64 %a, i64 %b) { 1699; CHECK-LABEL: @multi_use_in_phi( 1700; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 1701; CHECK: if: 1702; CHECK-NEXT: call void @dummy() 1703; CHECK-NEXT: br label [[JOIN]] 1704; CHECK: join: 1705; CHECK-NEXT: [[GEP1_B:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[A:%.*]] 1706; CHECK-NEXT: [[GEP2_B:%.*]] = getelementptr i8, ptr [[GEP1_B]], i64 [[B:%.*]] 1707; CHECK-NEXT: call void @use.ptr(ptr [[GEP1_B]]) 1708; CHECK-NEXT: ret ptr [[GEP2_B]] 1709; 1710 br i1 %cond, label %if, label %else 1711 1712if: 1713 call void @dummy() 1714 %gep1.a = getelementptr i8, ptr %p, i64 %a 1715 %gep2.a = getelementptr i8, ptr %gep1.a, i64 %b 1716 br label %join 1717 1718else: 1719 %gep1.b = getelementptr i8, ptr %p, i64 %a 1720 %gep2.b = getelementptr i8, ptr %gep1.b, i64 %b 1721 br label %join 1722 1723join: 1724 %phi1 = phi ptr [ %gep1.a, %if ], [ %gep1.b, %else ] 1725 %phi2 = phi ptr [ %gep2.a, %if ], [ %gep2.b, %else ] 1726 call void @use.ptr(ptr %phi1) 1727 ret ptr %phi2 1728} 1729 1730define ptr @multi_use_in_phi_inconsistent(i1 %cond, ptr %p, i64 %a, i64 %b) { 1731; CHECK-LABEL: @multi_use_in_phi_inconsistent( 1732; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 1733; CHECK: if: 1734; CHECK-NEXT: call void @dummy() 1735; CHECK-NEXT: [[GEP1_A:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[A:%.*]] 1736; CHECK-NEXT: br label [[JOIN:%.*]] 1737; CHECK: else: 1738; CHECK-NEXT: [[GEP1_B:%.*]] = getelementptr i8, ptr [[P]], i64 [[A]] 1739; CHECK-NEXT: br label [[JOIN]] 1740; CHECK: join: 1741; CHECK-NEXT: [[GEP1_B_SINK:%.*]] = phi ptr [ [[GEP1_B]], [[ELSE]] ], [ [[GEP1_A]], [[IF]] ] 1742; CHECK-NEXT: [[PHI1:%.*]] = phi ptr [ [[GEP1_A]], [[IF]] ], [ [[P]], [[ELSE]] ] 1743; CHECK-NEXT: [[GEP2_B:%.*]] = getelementptr i8, ptr [[GEP1_B_SINK]], i64 [[B:%.*]] 1744; CHECK-NEXT: call void @use.ptr(ptr [[PHI1]]) 1745; CHECK-NEXT: ret ptr [[GEP2_B]] 1746; 1747 br i1 %cond, label %if, label %else 1748 1749if: 1750 call void @dummy() 1751 %gep1.a = getelementptr i8, ptr %p, i64 %a 1752 %gep2.a = getelementptr i8, ptr %gep1.a, i64 %b 1753 br label %join 1754 1755else: 1756 %gep1.b = getelementptr i8, ptr %p, i64 %a 1757 %gep2.b = getelementptr i8, ptr %gep1.b, i64 %b 1758 br label %join 1759 1760join: 1761 %phi1 = phi ptr [ %gep1.a, %if ], [ %p, %else ] 1762 %phi2 = phi ptr [ %gep2.a, %if ], [ %gep2.b, %else ] 1763 call void @use.ptr(ptr %phi1) 1764 ret ptr %phi2 1765} 1766 1767define i64 @multi_use_in_block(i1 %cond, ptr %p, i64 %a, i64 %b) { 1768; CHECK-LABEL: @multi_use_in_block( 1769; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 1770; CHECK: if: 1771; CHECK-NEXT: call void @dummy() 1772; CHECK-NEXT: br label [[JOIN]] 1773; CHECK: join: 1774; CHECK-NEXT: [[GEP1_B:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[A:%.*]] 1775; CHECK-NEXT: [[V_B:%.*]] = load i64, ptr [[GEP1_B]], align 8 1776; CHECK-NEXT: [[GEP2_B:%.*]] = getelementptr i8, ptr [[GEP1_B]], i64 [[V_B]] 1777; CHECK-NEXT: call void @use.ptr(ptr [[GEP2_B]]) 1778; CHECK-NEXT: ret i64 [[V_B]] 1779; 1780 br i1 %cond, label %if, label %else 1781 1782if: 1783 call void @dummy() 1784 %gep1.a = getelementptr i8, ptr %p, i64 %a 1785 %v.a = load i64, ptr %gep1.a 1786 %gep2.a = getelementptr i8, ptr %gep1.a, i64 %v.a 1787 br label %join 1788 1789else: 1790 %gep1.b = getelementptr i8, ptr %p, i64 %a 1791 %v.b = load i64, ptr %gep1.b 1792 %gep2.b = getelementptr i8, ptr %gep1.b, i64 %v.b 1793 br label %join 1794 1795join: 1796 %phi1 = phi i64 [ %v.a, %if ], [ %v.b, %else ] 1797 %phi2 = phi ptr [ %gep2.a, %if ], [ %gep2.b, %else ] 1798 call void @use.ptr(ptr %phi2) 1799 ret i64 %phi1 1800} 1801 1802define i64 @multi_use_in_block_inconsistent(i1 %cond, ptr %p, i64 %a, i64 %b) { 1803; CHECK-LABEL: @multi_use_in_block_inconsistent( 1804; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 1805; CHECK: if: 1806; CHECK-NEXT: call void @dummy() 1807; CHECK-NEXT: [[GEP1_A:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[A:%.*]] 1808; CHECK-NEXT: [[V_A:%.*]] = load i64, ptr [[GEP1_A]], align 8 1809; CHECK-NEXT: [[GEP2_A:%.*]] = getelementptr i8, ptr [[GEP1_A]], i64 [[V_A]] 1810; CHECK-NEXT: br label [[JOIN:%.*]] 1811; CHECK: else: 1812; CHECK-NEXT: [[GEP1_B:%.*]] = getelementptr i8, ptr [[P]], i64 [[A]] 1813; CHECK-NEXT: [[V_B:%.*]] = load i64, ptr [[P]], align 8 1814; CHECK-NEXT: [[GEP2_B:%.*]] = getelementptr i8, ptr [[GEP1_B]], i64 [[V_B]] 1815; CHECK-NEXT: br label [[JOIN]] 1816; CHECK: join: 1817; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[V_A]], [[IF]] ], [ [[V_B]], [[ELSE]] ] 1818; CHECK-NEXT: [[PHI2:%.*]] = phi ptr [ [[GEP2_A]], [[IF]] ], [ [[GEP2_B]], [[ELSE]] ] 1819; CHECK-NEXT: call void @use.ptr(ptr [[PHI2]]) 1820; CHECK-NEXT: ret i64 [[PHI1]] 1821; 1822 br i1 %cond, label %if, label %else 1823 1824if: 1825 call void @dummy() 1826 %gep1.a = getelementptr i8, ptr %p, i64 %a 1827 %v.a = load i64, ptr %gep1.a 1828 %gep2.a = getelementptr i8, ptr %gep1.a, i64 %v.a 1829 br label %join 1830 1831else: 1832 %gep1.b = getelementptr i8, ptr %p, i64 %a 1833 %v.b = load i64, ptr %p 1834 %gep2.b = getelementptr i8, ptr %gep1.b, i64 %v.b 1835 br label %join 1836 1837join: 1838 %phi1 = phi i64 [ %v.a, %if ], [ %v.b, %else ] 1839 %phi2 = phi ptr [ %gep2.a, %if ], [ %gep2.b, %else ] 1840 call void @use.ptr(ptr %phi2) 1841 ret i64 %phi1 1842} 1843 1844define i64 @load_with_sunk_gep(i1 %cond, ptr %p, i64 %a, i64 %b) { 1845; CHECK-LABEL: @load_with_sunk_gep( 1846; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 1847; CHECK: if: 1848; CHECK-NEXT: call void @dummy() 1849; CHECK-NEXT: br label [[JOIN]] 1850; CHECK: join: 1851; CHECK-NEXT: [[B_SINK:%.*]] = phi i64 [ [[A:%.*]], [[IF]] ], [ [[B:%.*]], [[TMP0:%.*]] ] 1852; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[B_SINK]] 1853; CHECK-NEXT: [[V_B:%.*]] = load i64, ptr [[GEP_B]], align 8 1854; CHECK-NEXT: ret i64 [[V_B]] 1855; 1856 br i1 %cond, label %if, label %else 1857 1858if: 1859 call void @dummy() 1860 %gep.a = getelementptr i8, ptr %p, i64 %a 1861 %v.a = load i64, ptr %gep.a 1862 br label %join 1863 1864else: 1865 %gep.b = getelementptr i8, ptr %p, i64 %b 1866 %v.b = load i64, ptr %gep.b 1867 br label %join 1868 1869join: 1870 %v = phi i64 [ %v.a, %if ], [ %v.b, %else ] 1871 ret i64 %v 1872} 1873 1874define i64 @load_with_non_sunk_gep_both(i1 %cond, ptr %p.a, ptr %p.b, i64 %a, i64 %b) { 1875; CHECK-LABEL: @load_with_non_sunk_gep_both( 1876; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 1877; CHECK: if: 1878; CHECK-NEXT: call void @dummy() 1879; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i8, ptr [[P_A:%.*]], i64 [[A:%.*]] 1880; CHECK-NEXT: [[V_A:%.*]] = load i64, ptr [[GEP_A]], align 8 1881; CHECK-NEXT: br label [[JOIN:%.*]] 1882; CHECK: else: 1883; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[P_B:%.*]], i64 [[B:%.*]] 1884; CHECK-NEXT: [[V_B:%.*]] = load i64, ptr [[GEP_B]], align 8 1885; CHECK-NEXT: br label [[JOIN]] 1886; CHECK: join: 1887; CHECK-NEXT: [[V:%.*]] = phi i64 [ [[V_A]], [[IF]] ], [ [[V_B]], [[ELSE]] ] 1888; CHECK-NEXT: ret i64 [[V]] 1889; 1890 br i1 %cond, label %if, label %else 1891 1892if: 1893 call void @dummy() 1894 %gep.a = getelementptr i8, ptr %p.a, i64 %a 1895 %v.a = load i64, ptr %gep.a 1896 br label %join 1897 1898else: 1899 %gep.b = getelementptr i8, ptr %p.b, i64 %b 1900 %v.b = load i64, ptr %gep.b 1901 br label %join 1902 1903join: 1904 %v = phi i64 [ %v.a, %if ], [ %v.b, %else ] 1905 ret i64 %v 1906} 1907 1908define i64 @load_with_non_sunk_gep_left(i1 %cond, ptr %p.a, ptr %p.b, i64 %b) { 1909; CHECK-LABEL: @load_with_non_sunk_gep_left( 1910; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 1911; CHECK: if: 1912; CHECK-NEXT: call void @dummy() 1913; CHECK-NEXT: [[V_A:%.*]] = load i64, ptr [[P_A:%.*]], align 8 1914; CHECK-NEXT: br label [[JOIN:%.*]] 1915; CHECK: else: 1916; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[P_B:%.*]], i64 [[B:%.*]] 1917; CHECK-NEXT: [[V_B:%.*]] = load i64, ptr [[GEP_B]], align 8 1918; CHECK-NEXT: br label [[JOIN]] 1919; CHECK: join: 1920; CHECK-NEXT: [[V:%.*]] = phi i64 [ [[V_A]], [[IF]] ], [ [[V_B]], [[ELSE]] ] 1921; CHECK-NEXT: ret i64 [[V]] 1922; 1923 br i1 %cond, label %if, label %else 1924 1925if: 1926 call void @dummy() 1927 %v.a = load i64, ptr %p.a 1928 br label %join 1929 1930else: 1931 %gep.b = getelementptr i8, ptr %p.b, i64 %b 1932 %v.b = load i64, ptr %gep.b 1933 br label %join 1934 1935join: 1936 %v = phi i64 [ %v.a, %if ], [ %v.b, %else ] 1937 ret i64 %v 1938} 1939 1940define i64 @load_with_non_sunk_gep_right(i1 %cond, ptr %p.a, ptr %p.b, i64 %a) { 1941; CHECK-LABEL: @load_with_non_sunk_gep_right( 1942; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 1943; CHECK: if: 1944; CHECK-NEXT: call void @dummy() 1945; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i8, ptr [[P_A:%.*]], i64 [[A:%.*]] 1946; CHECK-NEXT: [[V_A:%.*]] = load i64, ptr [[GEP_A]], align 8 1947; CHECK-NEXT: br label [[JOIN:%.*]] 1948; CHECK: else: 1949; CHECK-NEXT: [[V_B:%.*]] = load i64, ptr [[P_B:%.*]], align 8 1950; CHECK-NEXT: br label [[JOIN]] 1951; CHECK: join: 1952; CHECK-NEXT: [[V:%.*]] = phi i64 [ [[V_A]], [[IF]] ], [ [[V_B]], [[ELSE]] ] 1953; CHECK-NEXT: ret i64 [[V]] 1954; 1955 br i1 %cond, label %if, label %else 1956 1957if: 1958 call void @dummy() 1959 %gep.a = getelementptr i8, ptr %p.a, i64 %a 1960 %v.a = load i64, ptr %gep.a 1961 br label %join 1962 1963else: 1964 %v.b = load i64, ptr %p.b 1965 br label %join 1966 1967join: 1968 %v = phi i64 [ %v.a, %if ], [ %v.b, %else ] 1969 ret i64 %v 1970} 1971 1972define void @store_with_non_sunk_gep(i1 %cond, ptr %p.a, ptr %p.b, i64 %a, i64 %b) { 1973; CHECK-LABEL: @store_with_non_sunk_gep( 1974; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 1975; CHECK: if: 1976; CHECK-NEXT: call void @dummy() 1977; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i8, ptr [[P_A:%.*]], i64 [[A:%.*]] 1978; CHECK-NEXT: store i64 0, ptr [[GEP_A]], align 8 1979; CHECK-NEXT: br label [[JOIN:%.*]] 1980; CHECK: else: 1981; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[P_B:%.*]], i64 [[B:%.*]] 1982; CHECK-NEXT: store i64 0, ptr [[GEP_B]], align 8 1983; CHECK-NEXT: br label [[JOIN]] 1984; CHECK: join: 1985; CHECK-NEXT: ret void 1986; 1987 br i1 %cond, label %if, label %else 1988 1989if: 1990 call void @dummy() 1991 %gep.a = getelementptr i8, ptr %p.a, i64 %a 1992 store i64 0, ptr %gep.a 1993 br label %join 1994 1995else: 1996 %gep.b = getelementptr i8, ptr %p.b, i64 %b 1997 store i64 0, ptr %gep.b 1998 br label %join 1999 2000join: 2001 ret void 2002} 2003 2004define void @store_with_non_sunk_gep_as_value(i1 %cond, ptr %p, ptr %p.a, ptr %p.b, i64 %a, i64 %b) { 2005; CHECK-LABEL: @store_with_non_sunk_gep_as_value( 2006; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 2007; CHECK: if: 2008; CHECK-NEXT: call void @dummy() 2009; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i8, ptr [[P_A:%.*]], i64 [[A:%.*]] 2010; CHECK-NEXT: br label [[JOIN:%.*]] 2011; CHECK: else: 2012; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[P_B:%.*]], i64 [[B:%.*]] 2013; CHECK-NEXT: br label [[JOIN]] 2014; CHECK: join: 2015; CHECK-NEXT: [[GEP_B_SINK:%.*]] = phi ptr [ [[GEP_B]], [[ELSE]] ], [ [[GEP_A]], [[IF]] ] 2016; CHECK-NEXT: store ptr [[GEP_B_SINK]], ptr [[P:%.*]], align 8 2017; CHECK-NEXT: ret void 2018; 2019 br i1 %cond, label %if, label %else 2020 2021if: 2022 call void @dummy() 2023 %gep.a = getelementptr i8, ptr %p.a, i64 %a 2024 store ptr %gep.a, ptr %p 2025 br label %join 2026 2027else: 2028 %gep.b = getelementptr i8, ptr %p.b, i64 %b 2029 store ptr %gep.b, ptr %p 2030 br label %join 2031 2032join: 2033 ret void 2034} 2035 2036define i32 @many_indirect_phis(i1 %cond, i32 %a, i32 %b) { 2037; CHECK-LABEL: @many_indirect_phis( 2038; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 2039; CHECK: if: 2040; CHECK-NEXT: call void @dummy() 2041; CHECK-NEXT: br label [[JOIN]] 2042; CHECK: join: 2043; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[A:%.*]], [[IF]] ], [ [[B:%.*]], [[TMP0:%.*]] ] 2044; CHECK-NEXT: [[DOTSINK3:%.*]] = phi i32 [ 10, [[IF]] ], [ 11, [[TMP0]] ] 2045; CHECK-NEXT: [[DOTSINK2:%.*]] = phi i32 [ 20, [[IF]] ], [ 21, [[TMP0]] ] 2046; CHECK-NEXT: [[DOTSINK1:%.*]] = phi i32 [ 30, [[IF]] ], [ 31, [[TMP0]] ] 2047; CHECK-NEXT: [[DOTSINK:%.*]] = phi i32 [ 40, [[IF]] ], [ 41, [[TMP0]] ] 2048; CHECK-NEXT: [[ADD_0_B:%.*]] = add i32 [[B_SINK]], 1 2049; CHECK-NEXT: [[ADD_1_B:%.*]] = add i32 [[ADD_0_B]], [[DOTSINK3]] 2050; CHECK-NEXT: [[ADD_2_B:%.*]] = add i32 [[ADD_1_B]], [[DOTSINK2]] 2051; CHECK-NEXT: [[ADD_3_B:%.*]] = add i32 [[ADD_2_B]], [[DOTSINK1]] 2052; CHECK-NEXT: [[ADD_4_B:%.*]] = add i32 [[ADD_3_B]], [[DOTSINK]] 2053; CHECK-NEXT: ret i32 [[ADD_4_B]] 2054; 2055 br i1 %cond, label %if, label %else 2056 2057if: 2058 call void @dummy() 2059 %add.0.a = add i32 %a, 1 2060 %add.1.a = add i32 %add.0.a, 10 2061 %add.2.a = add i32 %add.1.a, 20 2062 %add.3.a = add i32 %add.2.a, 30 2063 %add.4.a = add i32 %add.3.a, 40 2064 br label %join 2065 2066else: 2067 %add.0.b = add i32 %b, 1 2068 %add.1.b = add i32 %add.0.b, 11 2069 %add.2.b = add i32 %add.1.b, 21 2070 %add.3.b = add i32 %add.2.b, 31 2071 %add.4.b = add i32 %add.3.b, 41 2072 br label %join 2073 2074join: 2075 %phi = phi i32 [ %add.4.a, %if ], [ %add.4.b, %else ] 2076 ret i32 %phi 2077} 2078 2079define i32 @store_and_unrelated_many_phi_add(i1 %cond, ptr %p, i32 %a, i32 %b) { 2080; CHECK-LABEL: @store_and_unrelated_many_phi_add( 2081; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 2082; CHECK: if: 2083; CHECK-NEXT: call void @dummy() 2084; CHECK-NEXT: [[ADD_1:%.*]] = add i32 [[A:%.*]], 2 2085; CHECK-NEXT: br label [[JOIN:%.*]] 2086; CHECK: else: 2087; CHECK-NEXT: [[ADD_2:%.*]] = add i32 [[B:%.*]], 3 2088; CHECK-NEXT: br label [[JOIN]] 2089; CHECK: join: 2090; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ADD_1]], [[IF]] ], [ [[ADD_2]], [[ELSE]] ] 2091; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4 2092; CHECK-NEXT: ret i32 [[PHI]] 2093; 2094 br i1 %cond, label %if, label %else 2095 2096if: 2097 call void @dummy() 2098 %add.1 = add i32 %a, 2 2099 store i32 1, ptr %p 2100 br label %join 2101 2102else: 2103 %add.2 = add i32 %b, 3 2104 store i32 1, ptr %p 2105 br label %join 2106 2107join: 2108 %phi = phi i32 [ %add.1, %if ], [ %add.2, %else ] 2109 ret i32 %phi 2110} 2111 2112define i32 @store_and_related_many_phi_add(i1 %cond, ptr %p, i32 %a, i32 %b) { 2113; CHECK-LABEL: @store_and_related_many_phi_add( 2114; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 2115; CHECK: if: 2116; CHECK-NEXT: call void @dummy() 2117; CHECK-NEXT: [[ADD_1:%.*]] = add i32 [[A:%.*]], 2 2118; CHECK-NEXT: br label [[JOIN:%.*]] 2119; CHECK: else: 2120; CHECK-NEXT: [[ADD_2:%.*]] = add i32 [[B:%.*]], 3 2121; CHECK-NEXT: br label [[JOIN]] 2122; CHECK: join: 2123; CHECK-NEXT: [[ADD_2_SINK:%.*]] = phi i32 [ [[ADD_2]], [[ELSE]] ], [ [[ADD_1]], [[IF]] ] 2124; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ADD_1]], [[IF]] ], [ [[ADD_2]], [[ELSE]] ] 2125; CHECK-NEXT: store i32 [[ADD_2_SINK]], ptr [[P:%.*]], align 4 2126; CHECK-NEXT: ret i32 [[PHI]] 2127; 2128 br i1 %cond, label %if, label %else 2129 2130if: 2131 call void @dummy() 2132 %add.1 = add i32 %a, 2 2133 store i32 %add.1, ptr %p 2134 br label %join 2135 2136else: 2137 %add.2 = add i32 %b, 3 2138 store i32 %add.2, ptr %p 2139 br label %join 2140 2141join: 2142 %phi = phi i32 [ %add.1, %if ], [ %add.2, %else ] 2143 ret i32 %phi 2144} 2145 2146define i32 @store_and_unrelated_many_phi_add2(i1 %cond, ptr %p, i32 %a, i32 %b) { 2147; CHECK-LABEL: @store_and_unrelated_many_phi_add2( 2148; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 2149; CHECK: if: 2150; CHECK-NEXT: call void @dummy() 2151; CHECK-NEXT: [[ADD_1:%.*]] = add i32 [[A:%.*]], 2 2152; CHECK-NEXT: br label [[JOIN:%.*]] 2153; CHECK: else: 2154; CHECK-NEXT: [[ADD_2:%.*]] = add i32 [[B:%.*]], 3 2155; CHECK-NEXT: br label [[JOIN]] 2156; CHECK: join: 2157; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ADD_1]], [[IF]] ], [ [[ADD_2]], [[ELSE]] ] 2158; CHECK-NEXT: [[ADD_A_2:%.*]] = add i32 [[A]], 1 2159; CHECK-NEXT: store i32 [[ADD_A_2]], ptr [[P:%.*]], align 4 2160; CHECK-NEXT: ret i32 [[PHI]] 2161; 2162 br i1 %cond, label %if, label %else 2163 2164if: 2165 call void @dummy() 2166 %add.1 = add i32 %a, 2 2167 %add.a.1 = add i32 %a, 1 2168 store i32 %add.a.1, ptr %p 2169 br label %join 2170 2171else: 2172 %add.2 = add i32 %b, 3 2173 %add.a.2 = add i32 %a, 1 2174 store i32 %add.a.2, ptr %p 2175 br label %join 2176 2177join: 2178 %phi = phi i32 [ %add.1, %if ], [ %add.2, %else ] 2179 ret i32 %phi 2180} 2181 2182declare void @dummy() 2183declare void @use.ptr(ptr) 2184 2185!12 = !{i32 1} 2186