; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes='require<profile-summary>,function(chr,instcombine,simplifycfg)' -S | FileCheck %s declare void @foo() declare void @bar() ; Simple case. ; Roughly, ; t0 = *i ; if ((t0 & 1) != 0) // Likely true ; foo() ; if ((t0 & 2) != 0) // Likely true ; foo() ; -> ; t0 = *i ; if ((t0 & 3) != 0) { // Likely true ; foo() ; foo() ; } else { ; if ((t0 & 1) != 0) ; foo() ; if ((t0 & 2) != 0) ; foo() ; } define void @test_chr_1(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15:![0-9]+]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16:![0-9]+]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: ret void } ; Simple case with a cold block. ; Roughly, ; t0 = *i ; if ((t0 & 1) != 0) // Likely true ; foo() ; if ((t0 & 2) == 0) // Likely false ; bar() ; if ((t0 & 4) != 0) // Likely true ; foo() ; -> ; t0 = *i ; if ((t0 & 7) == 7) { // Likely true ; foo() ; foo() ; } else { ; if ((t0 & 1) != 0) ; foo() ; if ((t0 & 2) == 0) ; bar() ; if ((t0 & 4) != 0) ; foo() ; } define void @test_chr_1_1(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_1_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 7 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 7 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB5:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB2_NONCHR:%.*]], label [[BB3_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @bar() ; CHECK-NEXT: br label [[BB3_NONCHR]] ; CHECK: bb3.nonchr: ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP0]], 4 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: br i1 [[TMP7]], label [[BB5]], label [[BB4_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb4.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB5]] ; CHECK: bb5: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb2, label %bb3, !prof !15 bb2: call void @bar() br label %bb3 bb3: %5 = and i32 %0, 4 %6 = icmp eq i32 %5, 0 br i1 %6, label %bb5, label %bb4, !prof !15 bb4: call void @foo() br label %bb5 bb5: ret void } ; With an aggregate bit check. ; Roughly, ; t0 = *i ; if ((t0 & 255) != 0) // Likely true ; if ((t0 & 1) != 0) // Likely true ; foo() ; if ((t0 & 2) != 0) // Likely true ; foo() ; -> ; t0 = *i ; if ((t0 & 3) != 0) { // Likely true ; foo() ; foo() ; } else if ((t0 & 255) != 0) ; if ((t0 & 1) != 0) ; foo() ; if ((t0 & 2) != 0) ; foo() ; } define void @test_chr_2(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb1: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB4:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 255 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB4]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB2_NONCHR:%.*]], label [[BB1_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: br i1 [[TMP7]], label [[BB4]], label [[BB3_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb3.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB4]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB2_NONCHR]] ; CHECK: bb4: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 255 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb4, label %bb0, !prof !15 bb0: %3 = and i32 %0, 1 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb2, label %bb1, !prof !15 bb1: call void @foo() br label %bb2 bb2: %5 = and i32 %0, 2 %6 = icmp eq i32 %5, 0 br i1 %6, label %bb4, label %bb3, !prof !15 bb3: call void @foo() br label %bb4 bb4: ret void } ; Split case. ; Roughly, ; t1 = *i ; if ((t1 & 1) != 0) // Likely true ; foo() ; if ((t1 & 2) != 0) // Likely true ; foo() ; t2 = *i ; if ((t2 & 4) != 0) // Likely true ; foo() ; if ((t2 & 8) != 0) // Likely true ; foo() ; -> ; t1 = *i ; if ((t1 & 3) != 0) { // Likely true ; foo() ; foo() ; } else { ; if ((t1 & 1) != 0) ; foo() ; if ((t1 & 2) != 0) ; foo() ; } ; t2 = *i ; if ((t2 & 12) != 0) { // Likely true ; foo() ; foo() ; } else { ; if ((t2 & 4) != 0) ; foo() ; if ((t2 & 8) != 0) ; foo() ; } define void @test_chr_3(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[I]], align 4 ; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP6]], 12 ; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 12 ; CHECK-NEXT: br i1 [[TMP8]], label [[BB4:%.*]], label [[BB3_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb4: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB7:%.*]] ; CHECK: bb3.split.nonchr: ; CHECK-NEXT: [[TMP9:%.*]] = and i32 [[TMP6]], 4 ; CHECK-NEXT: [[DOTNOT1:%.*]] = icmp eq i32 [[TMP9]], 0 ; CHECK-NEXT: br i1 [[DOTNOT1]], label [[BB5_NONCHR:%.*]], label [[BB4_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb4.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB5_NONCHR]] ; CHECK: bb5.nonchr: ; CHECK-NEXT: [[TMP10:%.*]] = and i32 [[TMP6]], 8 ; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0 ; CHECK-NEXT: br i1 [[TMP11]], label [[BB7]], label [[BB6_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb6.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB7]] ; CHECK: bb7: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: %5 = load i32, ptr %i %6 = and i32 %5, 4 %7 = icmp eq i32 %6, 0 br i1 %7, label %bb5, label %bb4, !prof !15 bb4: call void @foo() br label %bb5 bb5: %8 = and i32 %5, 8 %9 = icmp eq i32 %8, 0 br i1 %9, label %bb7, label %bb6, !prof !15 bb6: call void @foo() br label %bb7 bb7: ret void } ; Selects. ; Roughly, ; t0 = *i ; sum1 = (t0 & 1) ? sum0 : (sum0 + 42) // Likely false ; sum2 = (t0 & 2) ? sum1 : (sum1 + 43) // Likely false ; return sum2 ; -> ; t0 = *i ; if ((t0 & 3) == 3) ; return sum0 + 85 ; else { ; sum1 = (t0 & 1) ? sum0 : (sum0 + 42) ; sum2 = (t0 & 2) ? sum1 : (sum1 + 43) ; return sum2 ; } define i32 @test_chr_4(ptr %i, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_4( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[DOTFR1:%.*]] = freeze i32 [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[DOTFR1]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: common.ret: ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP3:%.*]], [[ENTRY_SPLIT]] ], [ [[SUM2_NONCHR:%.*]], [[ENTRY_SPLIT_NONCHR]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; CHECK: entry.split: ; CHECK-NEXT: [[TMP3]] = add i32 [[SUM0:%.*]], 85 ; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[SUM0]], 42 ; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[DOTFR1]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP5]], 0 ; CHECK-NEXT: [[SUM1_NONCHR:%.*]] = select i1 [[DOTNOT]], i32 [[SUM0]], i32 [[TMP4]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[DOTFR1]], 2 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[SUM1_NONCHR]], 43 ; CHECK-NEXT: [[SUM2_NONCHR]] = select i1 [[TMP7]], i32 [[SUM1_NONCHR]], i32 [[TMP8]], !prof [[PROF16]] ; CHECK-NEXT: br label [[COMMON_RET]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 %3 = add i32 %sum0, 42 %sum1 = select i1 %2, i32 %sum0, i32 %3, !prof !15 %4 = and i32 %0, 2 %5 = icmp eq i32 %4, 0 %6 = add i32 %sum1, 43 %sum2 = select i1 %5, i32 %sum1, i32 %6, !prof !15 ret i32 %sum2 } ; Selects + Brs ; Roughly, ; t0 = *i ; if ((t0 & 255) != 0) { // Likely true ; sum = (t0 & 1) ? sum0 : (sum0 + 42) // Likely false ; sum = (t0 & 2) ? sum : (sum + 43) // Likely false ; if ((t0 & 4) != 0) { // Likely true ; sum3 = sum + 44 ; sum = (t0 & 8) ? sum3 : (sum3 + 44) // Likely false ; } ; } ; return sum ; -> ; t0 = *i ; if ((t0 & 15) != 15) { // Likely true ; sum = sum0 + 173 ; } else if ((t0 & 255) != 0) { ; sum = (t0 & 1) ? sum0 : (sum0 + 42) ; sum = (t0 & 2) ? sum : (sum + 43) ; if ((t0 & 4) != 0) { ; sum3 = sum + 44 ; sum = (t0 & 8) ? sum3 : (sum3 + 44) ; } ; } ; return sum define i32 @test_chr_5(ptr %i, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_5( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[DOTFR1:%.*]] = freeze i32 [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[DOTFR1]], 15 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 15 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85 ; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[SUM0]], 173 ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[DOTFR1]], 255 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP5]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[DOTFR1]], 1 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[SUM0]], 42 ; CHECK-NEXT: [[SUM1_NONCHR:%.*]] = select i1 [[TMP7]], i32 [[SUM0]], i32 [[TMP8]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP9:%.*]] = and i32 [[DOTFR1]], 2 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 0 ; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[SUM1_NONCHR]], 43 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[TMP10]], i32 [[SUM1_NONCHR]], i32 [[TMP11]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP12:%.*]] = and i32 [[DOTFR1]], 4 ; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP12]], 0 ; CHECK-NEXT: [[TMP14:%.*]] = and i32 [[DOTFR1]], 8 ; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i32 [[TMP14]], 0 ; CHECK-NEXT: [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP15]], i32 44, i32 88 ; CHECK-NEXT: [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]] ; CHECK-NEXT: [[SUM5_NONCHR:%.*]] = select i1 [[TMP13]], i32 [[SUM2_NONCHR]], i32 [[SUM4_NONCHR]], !prof [[PROF16]] ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[SUM6:%.*]] = phi i32 [ [[TMP4]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM5_NONCHR]], [[BB0_NONCHR]] ] ; CHECK-NEXT: ret i32 [[SUM6]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 255 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb3, label %bb0, !prof !15 bb0: %3 = and i32 %0, 1 %4 = icmp eq i32 %3, 0 %5 = add i32 %sum0, 42 %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15 %6 = and i32 %0, 2 %7 = icmp eq i32 %6, 0 %8 = add i32 %sum1, 43 %sum2 = select i1 %7, i32 %sum1, i32 %8, !prof !15 %9 = and i32 %0, 4 %10 = icmp eq i32 %9, 0 br i1 %10, label %bb2, label %bb1, !prof !15 bb1: %sum3 = add i32 %sum2, 44 %11 = and i32 %0, 8 %12 = icmp eq i32 %11, 0 %13 = add i32 %sum3, 44 %sum4 = select i1 %12, i32 %sum3, i32 %13, !prof !15 br label %bb2 bb2: %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ] br label %bb3 bb3: %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ] ret i32 %sum6 } ; Selects + Brs with a scope split in the middle ; Roughly, ; t0 = *i ; if ((t0 & 255) != 0) { // Likely true ; sum = (t0 & 1) ? sum0 : (sum0 + 42) // Likely false ; sum = (t0 & 2) ? sum : (sum + 43) // Likely false ; if ((sum0 & 4) != 0) { // Likely true. The condition doesn't use v. ; sum3 = sum + 44 ; sum = (t0 & 8) ? sum3 : (sum3 + 44) // Likely false ; } ; } ; return sum ; -> ; t0 = *i ; if ((sum0 & 4) != 0 & (t0 & 11) != 11) { // Likely true ; sum = sum0 + 173 ; } else if ((t0 & 255) != 0) { ; sum = (t0 & 1) ? sum0 : (sum0 + 42) ; sum = (t0 & 2) ? sum : (sum + 43) ; if ((sum0 & 4) != 0) { ; sum3 = sum + 44 ; sum = (t0 & 8) ? sum3 : (sum3 + 44) ; } ; } ; return sum define i32 @test_chr_5_1(ptr %i, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_5_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[DOTFR1:%.*]] = freeze i32 [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[SUM0:%.*]], 4 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[DOTFR1]], 11 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 11 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i1 [[TMP2]], i1 false ; CHECK-NEXT: br i1 [[TMP5]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[SUM0]], 85 ; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[SUM0]], 173 ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP8:%.*]] = and i32 [[DOTFR1]], 255 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP8]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: [[TMP9:%.*]] = and i32 [[DOTFR1]], 1 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 0 ; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[SUM0]], 42 ; CHECK-NEXT: [[SUM1_NONCHR:%.*]] = select i1 [[TMP10]], i32 [[SUM0]], i32 [[TMP11]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP12:%.*]] = and i32 [[DOTFR1]], 2 ; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP12]], 0 ; CHECK-NEXT: [[TMP14:%.*]] = add i32 [[SUM1_NONCHR]], 43 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[TMP13]], i32 [[SUM1_NONCHR]], i32 [[TMP14]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP15:%.*]] = and i32 [[SUM0]], 4 ; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0 ; CHECK-NEXT: [[TMP17:%.*]] = and i32 [[DOTFR1]], 8 ; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i32 [[TMP17]], 0 ; CHECK-NEXT: [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP18]], i32 44, i32 88 ; CHECK-NEXT: [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]] ; CHECK-NEXT: [[SUM5_NONCHR:%.*]] = select i1 [[TMP16]], i32 [[SUM2_NONCHR]], i32 [[SUM4_NONCHR]], !prof [[PROF16]] ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[SUM6:%.*]] = phi i32 [ [[TMP7]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM5_NONCHR]], [[BB0_NONCHR]] ] ; CHECK-NEXT: ret i32 [[SUM6]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 255 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb3, label %bb0, !prof !15 bb0: %3 = and i32 %0, 1 %4 = icmp eq i32 %3, 0 %5 = add i32 %sum0, 42 %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15 %6 = and i32 %0, 2 %7 = icmp eq i32 %6, 0 %8 = add i32 %sum1, 43 %sum2 = select i1 %7, i32 %sum1, i32 %8, !prof !15 %9 = and i32 %sum0, 4 ; Split %10 = icmp eq i32 %9, 0 br i1 %10, label %bb2, label %bb1, !prof !15 bb1: %sum3 = add i32 %sum2, 44 %11 = and i32 %0, 8 %12 = icmp eq i32 %11, 0 %13 = add i32 %sum3, 44 %sum4 = select i1 %12, i32 %sum3, i32 %13, !prof !15 br label %bb2 bb2: %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ] br label %bb3 bb3: %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ] ret i32 %sum6 } ; Selects + Brs, non-matching bases ; Roughly, ; i0 = *i ; j0 = *j ; if ((i0 & 255) != 0) { // Likely true ; sum = (i0 & 2) ? sum0 : (sum0 + 43) // Likely false ; if ((j0 & 4) != 0) { // Likely true. The condition uses j0, not i0. ; sum3 = sum + 44 ; sum = (i0 & 8) ? sum3 : (sum3 + 44) // Likely false ; } ; } ; return sum ; -> ; i0 = *i ; j0 = *j ; if ((j0 & 4) != 0 & (i0 & 10) != 10) { // Likely true ; sum = sum0 + 131 ; } else if ((i0 & 255) != 0) { ; sum = (i0 & 2) ? sum0 : (sum0 + 43) ; if ((j0 & 4) != 0) { ; sum3 = sum + 44 ; sum = (i0 & 8) ? sum3 : (sum3 + 44) ; } ; } ; return sum define i32 @test_chr_6(ptr %i, ptr %j, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_6( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[I0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[I0_FR:%.*]] = freeze i32 [[I0]] ; CHECK-NEXT: [[J0:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: [[V9:%.*]] = and i32 [[J0]], 4 ; CHECK-NEXT: [[V10:%.*]] = icmp ne i32 [[V9]], 0 ; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[I0_FR]], 10 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 10 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[V10]], i1 false ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: [[V8:%.*]] = add i32 [[SUM0:%.*]], 43 ; CHECK-NEXT: [[V13:%.*]] = add i32 [[SUM0]], 131 ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[V1:%.*]] = and i32 [[I0_FR]], 255 ; CHECK-NEXT: [[V2_NOT:%.*]] = icmp eq i32 [[V1]], 0 ; CHECK-NEXT: br i1 [[V2_NOT]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: [[V3_NONCHR:%.*]] = and i32 [[I0_FR]], 2 ; CHECK-NEXT: [[V4_NONCHR:%.*]] = icmp eq i32 [[V3_NONCHR]], 0 ; CHECK-NEXT: [[V8_NONCHR:%.*]] = add i32 [[SUM0]], 43 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[V4_NONCHR]], i32 [[SUM0]], i32 [[V8_NONCHR]], !prof [[PROF16]] ; CHECK-NEXT: [[V9_NONCHR:%.*]] = and i32 [[J0]], 4 ; CHECK-NEXT: [[V10_NONCHR:%.*]] = icmp eq i32 [[V9_NONCHR]], 0 ; CHECK-NEXT: [[V11_NONCHR:%.*]] = and i32 [[I0_FR]], 8 ; CHECK-NEXT: [[V12_NONCHR:%.*]] = icmp eq i32 [[V11_NONCHR]], 0 ; CHECK-NEXT: [[SUM4_NONCHR_V:%.*]] = select i1 [[V12_NONCHR]], i32 44, i32 88 ; CHECK-NEXT: [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]] ; CHECK-NEXT: [[SUM5_NONCHR:%.*]] = select i1 [[V10_NONCHR]], i32 [[SUM2_NONCHR]], i32 [[SUM4_NONCHR]], !prof [[PROF16]] ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[SUM6:%.*]] = phi i32 [ [[V13]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM5_NONCHR]], [[BB0_NONCHR]] ] ; CHECK-NEXT: ret i32 [[SUM6]] ; entry: %i0 = load i32, ptr %i %j0 = load i32, ptr %j %v1 = and i32 %i0, 255 %v2 = icmp eq i32 %v1, 0 br i1 %v2, label %bb3, label %bb0, !prof !15 bb0: %v3 = and i32 %i0, 2 %v4 = icmp eq i32 %v3, 0 %v8 = add i32 %sum0, 43 %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15 %v9 = and i32 %j0, 4 %v10 = icmp eq i32 %v9, 0 br i1 %v10, label %bb2, label %bb1, !prof !15 bb1: %sum3 = add i32 %sum2, 44 %v11 = and i32 %i0, 8 %v12 = icmp eq i32 %v11, 0 %v13 = add i32 %sum3, 44 %sum4 = select i1 %v12, i32 %sum3, i32 %v13, !prof !15 br label %bb2 bb2: %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ] br label %bb3 bb3: %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ] ret i32 %sum6 } ; Selects + Brs, the branch condition can't be hoisted to be merged with a ; select. No CHR happens. ; Roughly, ; i0 = *i ; sum = ((i0 & 2) == 0) ? sum0 : (sum0 + 43) // Likely false ; foo(); ; j0 = *j ; if ((j0 & 4) != 0) { // Likely true ; foo(); ; sum = sum + 44 ; } ; return sum ; -> ; (no change) define i32 @test_chr_7(ptr %i, ptr %j, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_7( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[I0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[V3:%.*]] = and i32 [[I0]], 2 ; CHECK-NEXT: [[V4:%.*]] = icmp eq i32 [[V3]], 0 ; CHECK-NEXT: [[V8:%.*]] = add i32 [[SUM0:%.*]], 43 ; CHECK-NEXT: [[SUM2:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof [[PROF16]] ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[J0:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: [[V9:%.*]] = and i32 [[J0]], 4 ; CHECK-NEXT: [[V10:%.*]] = icmp eq i32 [[V9]], 0 ; CHECK-NEXT: br i1 [[V10]], label [[BB2:%.*]], label [[BB1:%.*]], !prof [[PROF16]] ; CHECK: bb1: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[SUM4:%.*]] = add i32 [[SUM2]], 44 ; CHECK-NEXT: br label [[BB2]] ; CHECK: bb2: ; CHECK-NEXT: [[SUM5:%.*]] = phi i32 [ [[SUM2]], [[ENTRY:%.*]] ], [ [[SUM4]], [[BB1]] ] ; CHECK-NEXT: ret i32 [[SUM5]] ; entry: %i0 = load i32, ptr %i %v3 = and i32 %i0, 2 %v4 = icmp eq i32 %v3, 0 %v8 = add i32 %sum0, 43 %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15 call void @foo() %j0 = load i32, ptr %j %v9 = and i32 %j0, 4 %v10 = icmp eq i32 %v9, 0 br i1 %v10, label %bb2, label %bb1, !prof !15 ; %v10 can't be hoisted above the above select bb1: call void @foo() %sum4 = add i32 %sum2, 44 br label %bb2 bb2: %sum5 = phi i32 [ %sum2, %entry ], [ %sum4, %bb1 ] ret i32 %sum5 } ; Selects + Brs, the branch condition can't be hoisted to be merged with the ; selects. Dropping the select. ; Roughly, ; i0 = *i ; sum = ((i0 & 2) == 0) ? sum0 : (sum0 + 43) // Likely false ; foo(); ; j0 = *j ; if ((j0 & 4) != 0) // Likely true ; foo() ; if ((j0 & 8) != 0) // Likely true ; foo() ; return sum ; -> ; i0 = *i ; sum = ((i0 & 2) == 0) ? sum0 : (sum0 + 43) // Likely false ; foo(); ; j0 = *j ; if ((j0 & 12) != 12) { // Likely true ; foo() ; foo() ; } else { ; if ((j0 & 4) != 0) ; foo() ; if ((j0 & 8) != 0) ; foo() ; } ; return sum define i32 @test_chr_7_1(ptr %i, ptr %j, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_7_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[I0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[J0:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[J0]], 12 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 12 ; CHECK-NEXT: br i1 [[TMP1]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[V9:%.*]] = and i32 [[J0]], 4 ; CHECK-NEXT: [[V10_NOT:%.*]] = icmp eq i32 [[V9]], 0 ; CHECK-NEXT: br i1 [[V10_NOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[V11_NONCHR:%.*]] = and i32 [[J0]], 8 ; CHECK-NEXT: [[V12_NONCHR:%.*]] = icmp eq i32 [[V11_NONCHR]], 0 ; CHECK-NEXT: br i1 [[V12_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[V3:%.*]] = and i32 [[I0]], 2 ; CHECK-NEXT: [[V4:%.*]] = icmp eq i32 [[V3]], 0 ; CHECK-NEXT: [[V8:%.*]] = add i32 [[SUM0:%.*]], 43 ; CHECK-NEXT: [[SUM2:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof [[PROF16]] ; CHECK-NEXT: ret i32 [[SUM2]] ; entry: %i0 = load i32, ptr %i %v3 = and i32 %i0, 2 %v4 = icmp eq i32 %v3, 0 %v8 = add i32 %sum0, 43 %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15 call void @foo() %j0 = load i32, ptr %j %v9 = and i32 %j0, 4 %v10 = icmp eq i32 %v9, 0 br i1 %v10, label %bb1, label %bb0, !prof !15 ; %v10 can't be hoisted above the above select bb0: call void @foo() br label %bb1 bb1: %v11 = and i32 %j0, 8 %v12 = icmp eq i32 %v11, 0 br i1 %v12, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: ret i32 %sum2 } ; Branches aren't biased enough. No CHR happens. ; Roughly, ; t0 = *i ; if ((t0 & 1) != 0) // Not biased ; foo() ; if ((t0 & 2) != 0) // Not biased ; foo() ; -> ; (no change) define void @test_chr_8(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_8( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF17:![0-9]+]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[TMP4]], label [[BB3:%.*]], label [[BB2:%.*]], !prof [[PROF17]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !16 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !16 bb2: call void @foo() br label %bb3 bb3: ret void } ; With an existing phi at the exit. ; Roughly, ; t = *i ; if ((t0 & 1) != 0) // Likely true ; foo() ; if ((t0 & 2) != 0) { // Likely true ; t = *j ; foo() ; } ; // There's a phi for t here. ; return t ; -> ; t = *i ; if ((t & 3) == 3) { // Likely true ; foo() ; t = *j ; foo() ; } else { ; if ((t & 1) != 0) ; foo() ; if ((t & 2) != 0) { ; t = *j ; foo() ; } ; } ; // There's a phi for t here. ; return t define i32 @test_chr_9(ptr %i, ptr %j) !prof !14 { ; CHECK-LABEL: @test_chr_9( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0 ; CHECK-NEXT: br i1 [[TMP6]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[J]], align 4 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP0]], [[BB1_NONCHR]] ], [ [[TMP7]], [[BB2_NONCHR]] ] ; CHECK-NEXT: ret i32 [[TMP8]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !15 bb2: %5 = load i32, ptr %j call void @foo() br label %bb3 bb3: %6 = phi i32 [ %0, %bb1 ], [ %5, %bb2 ] ret i32 %6 } ; With no phi at the exit, but the exit needs a phi inserted after CHR. ; Roughly, ; t0 = *i ; if ((t0 & 1) != 0) // Likely true ; foo() ; t1 = *j ; if ((t1 & 2) != 0) // Likely true ; foo() ; return (t1 * 42) - (t1 - 99) ; -> ; t0 = *i ; if ((t0 & 3) == 3) { // Likely true ; foo() ; t1 = *j ; foo() ; } else { ; if ((t0 & 1) != 0) ; foo() ; if ((t0 & 2) != 0) { ; t1 = *j ; foo() ; } ; } ; // A new phi for t1 is inserted here. ; return (t1 * 42) - (t1 - 99) define i32 @test_chr_10(ptr %i, ptr %j) !prof !14 { ; CHECK-LABEL: @test_chr_10( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[J]], align 4 ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: br i1 [[TMP7]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP5]], [[BB2_NONCHR]] ], [ [[TMP5]], [[BB1_NONCHR]] ] ; CHECK-NEXT: [[TMP9:%.*]] = mul i32 [[TMP8]], 42 ; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[TMP8]], -99 ; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[TMP9]], [[TMP10]] ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = load i32, ptr %j %4 = and i32 %0, 2 %5 = icmp eq i32 %4, 0 br i1 %5, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: %6 = mul i32 %3, 42 %7 = sub i32 %3, 99 %8 = add i32 %6, %7 ret i32 %8 } ; Test a case where there are two use-def chain paths to the same value (t0) ; from the branch condition. This is a regression test for an old bug that ; caused a bad hoisting that moves (hoists) a value (%conv) twice to the end of ; the %entry block (once for %div and once for %mul16) and put a use ahead of ; its definition like: ; %entry: ; ... ; %div = fdiv double 1.000000e+00, %conv ; %conv = sitofp i32 %0 to double ; %mul16 = fmul double %div, %conv ; ; Roughly, ; t0 = *i ; if ((t0 & 1) != 0) // Likely true ; foo() ; // there are two use-def paths from the branch condition to t0. ; if ((1.0 / t0) * t0 < 1) // Likely true ; foo() ; -> ; t0 = *i ; if ((t0 & 1) != 0 & (1.0 / t0) * t0 > 0) { // Likely true ; foo() ; foo() ; } else { ; if ((t0 & 1) != 0) ; foo() ; if ((1.0 / t0) * t0 < 1) // Likely true ; foo() ; } define void @test_chr_11(ptr %i, i32 %x) !prof !14 { ; CHECK-LABEL: @test_chr_11( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP0]] to double ; CHECK-NEXT: [[DIV:%.*]] = fdiv double 1.000000e+00, [[CONV]] ; CHECK-NEXT: [[MUL16:%.*]] = fmul double [[DIV]], [[CONV]] ; CHECK-NEXT: [[CONV717:%.*]] = fptosi double [[MUL16]] to i32 ; CHECK-NEXT: [[CMP18:%.*]] = icmp sgt i32 [[CONV717]], 0 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i1 [[CMP18]], i1 false ; CHECK-NEXT: br i1 [[TMP3]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0_NONCHR:%.*]], label [[BB1_NONCHR:%.*]], !prof [[PROF18:![0-9]+]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[CONV_NONCHR:%.*]] = sitofp i32 [[TMP0]] to double ; CHECK-NEXT: [[DIV_NONCHR:%.*]] = fdiv double 1.000000e+00, [[CONV_NONCHR]] ; CHECK-NEXT: [[MUL16_NONCHR:%.*]] = fmul double [[DIV_NONCHR]], [[CONV_NONCHR]] ; CHECK-NEXT: [[CONV717_NONCHR:%.*]] = fptosi double [[MUL16_NONCHR]] to i32 ; CHECK-NEXT: [[CMP18_NONCHR:%.*]] = icmp slt i32 [[CONV717_NONCHR]], 1 ; CHECK-NEXT: br i1 [[CMP18_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %conv = sitofp i32 %0 to double %div = fdiv double 1.000000e+00, %conv %mul16 = fmul double %div, %conv %conv717 = fptosi double %mul16 to i32 %cmp18 = icmp slt i32 %conv717, 1 br i1 %cmp18, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: ret void } ; Selects + unrelated br only define i32 @test_chr_12(ptr %i, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_12( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[DOTFR1:%.*]] = freeze i32 [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[DOTFR1]], 255 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB3:%.*]], label [[BB0:%.*]], !prof [[PROF16]] ; CHECK: bb0: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[DOTFR1]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[SUM0:%.*]], 42 ; CHECK-NEXT: [[SUM1:%.*]] = select i1 [[TMP4]], i32 [[SUM0]], i32 [[TMP5]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[DOTFR1]], 2 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[SUM1]], 43 ; CHECK-NEXT: [[SUM2:%.*]] = select i1 [[TMP7]], i32 [[SUM1]], i32 [[TMP8]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[I]], align 4 ; CHECK-NEXT: [[TMP10:%.*]] = icmp ne i32 [[TMP9]], 0 ; CHECK-NEXT: [[TMP11:%.*]] = and i32 [[DOTFR1]], 8 ; CHECK-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 ; CHECK-NEXT: [[TMP13:%.*]] = and i1 [[TMP10]], [[TMP12]] ; CHECK-NEXT: br i1 [[TMP13]], label [[BB1:%.*]], label [[BB0_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb1: ; CHECK-NEXT: [[TMP14:%.*]] = add i32 [[SUM2]], 88 ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb0.split.nonchr: ; CHECK-NEXT: br i1 [[TMP10]], label [[BB1_NONCHR:%.*]], label [[BB3]], !prof [[PROF18]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP15:%.*]] = and i32 [[DOTFR1]], 8 ; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0 ; CHECK-NEXT: [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP16]], i32 44, i32 88, !prof [[PROF16]] ; CHECK-NEXT: [[SUM4_NONCHR:%.*]] = add i32 [[SUM2]], [[SUM4_NONCHR_V]] ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[SUM6:%.*]] = phi i32 [ [[SUM0]], [[ENTRY:%.*]] ], [ [[TMP14]], [[BB1]] ], [ [[SUM2]], [[BB0_SPLIT_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ] ; CHECK-NEXT: ret i32 [[SUM6]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 255 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb3, label %bb0, !prof !15 bb0: %3 = and i32 %0, 1 %4 = icmp eq i32 %3, 0 %5 = add i32 %sum0, 42 %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15 %6 = and i32 %0, 2 %7 = icmp eq i32 %6, 0 %8 = add i32 %sum1, 43 %sum2 = select i1 %7, i32 %sum1, i32 %8, !prof !15 %9 = load i32, ptr %i %10 = icmp eq i32 %9, 0 br i1 %10, label %bb2, label %bb1, !prof !15 bb1: %sum3 = add i32 %sum2, 44 %11 = and i32 %0, 8 %12 = icmp eq i32 %11, 0 %13 = add i32 %sum3, 44 %sum4 = select i1 %12, i32 %sum3, i32 %13, !prof !15 br label %bb2 bb2: %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ] br label %bb3 bb3: %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ] ret i32 %sum6 } ; In the second CHR, a condition value depends on a trivial phi that's inserted ; by the first CHR. ; Roughly, ; i0 = *i ; v2 = (z != 1) ? pred : true // Likely false ; if (z == 0 & pred) // Likely false ; foo() ; j0 = *j ; sum2 = ((i0 & 2) == j0) ? sum0 : (sum0 + 43) // Likely false ; sum3 = ((i0 == j0) ? sum0 : (sum0 + 43) // Likely false ; foo() ; if ((i0 & 4) == 0) // Unbiased ; foo() ; return i0 + sum3 ; -> ; i0 = *i ; if (z != 1 & (z == 0 & pred)) // First CHR ; foo() ; // A trivial phi for i0 is inserted here by the first CHR (which gets removed ; // later) and the subsequent branch condition (for the second CHR) uses it. ; j0 = *j ; if ((i0 & 2) != j0 & i0 != j0) { // Second CHR ; sum3 = sum0 + 43 ; foo() ; if (i0 & 4) == 0) ; foo() ; } else { ; sum3 = (i0 == j0) ? sum0 : (sum0 + 43) ; foo() ; if (i0 & 4) == 0) ; foo() ; } ; return i0 + sum3 define i32 @test_chr_14(ptr %i, ptr %j, i32 %sum0, i1 %pred, i32 %z) !prof !14 { ; CHECK-LABEL: @test_chr_14( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[Z_FR:%.*]] = freeze i32 [[Z:%.*]] ; CHECK-NEXT: [[I0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[Z_FR]], 1 ; CHECK-NEXT: br i1 [[V1]], label [[BB1:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[V0:%.*]] = icmp eq i32 [[Z_FR]], 0 ; CHECK-NEXT: [[V3_NONCHR:%.*]] = and i1 [[V0]], [[PRED:%.*]] ; CHECK-NEXT: br i1 [[V3_NONCHR]], label [[BB0_NONCHR:%.*]], label [[BB1]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[J0:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: [[V6:%.*]] = and i32 [[I0]], 2 ; CHECK-NEXT: [[V4:%.*]] = icmp ne i32 [[V6]], [[J0]] ; CHECK-NEXT: [[V8:%.*]] = add i32 [[SUM0:%.*]], 43 ; CHECK-NEXT: [[V5:%.*]] = icmp ne i32 [[I0]], [[J0]] ; CHECK-NEXT: [[TMP0:%.*]] = freeze i1 [[V4]] ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[V5]] ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP0]], [[TMP1]] ; CHECK-NEXT: br i1 [[TMP2]], label [[BB1_SPLIT:%.*]], label [[BB1_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb1.split: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[V9:%.*]] = and i32 [[I0]], 4 ; CHECK-NEXT: [[V10:%.*]] = icmp eq i32 [[V9]], 0 ; CHECK-NEXT: br i1 [[V10]], label [[BB3:%.*]], label [[BB2:%.*]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb1.split.nonchr: ; CHECK-NEXT: [[V5_NONCHR:%.*]] = icmp eq i32 [[I0]], [[J0]] ; CHECK-NEXT: [[SUM3_NONCHR:%.*]] = select i1 [[V5_NONCHR]], i32 [[SUM0]], i32 [[V8]], !prof [[PROF16]] ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[V9_NONCHR:%.*]] = and i32 [[I0]], 4 ; CHECK-NEXT: [[V10_NONCHR:%.*]] = icmp eq i32 [[V9_NONCHR]], 0 ; CHECK-NEXT: br i1 [[V10_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[V8]], [[BB2]] ], [ [[V8]], [[BB1_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB2_NONCHR]] ], [ [[SUM3_NONCHR]], [[BB1_SPLIT_NONCHR]] ] ; CHECK-NEXT: [[V11:%.*]] = add i32 [[I0]], [[TMP3]] ; CHECK-NEXT: ret i32 [[V11]] ; entry: %i0 = load i32, ptr %i %v0 = icmp eq i32 %z, 0 %v1 = icmp ne i32 %z, 1 %v2 = select i1 %v1, i1 %pred, i1 true, !prof !15 %v3 = and i1 %v0, %pred br i1 %v3, label %bb0, label %bb1, !prof !15 bb0: call void @foo() br label %bb1 bb1: %j0 = load i32, ptr %j %v6 = and i32 %i0, 2 %v4 = icmp eq i32 %v6, %j0 %v8 = add i32 %sum0, 43 %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15 %v5 = icmp eq i32 %i0, %j0 %sum3 = select i1 %v5, i32 %sum0, i32 %v8, !prof !15 call void @foo() %v9 = and i32 %i0, 4 %v10 = icmp eq i32 %v9, 0 br i1 %v10, label %bb3, label %bb2 bb2: call void @foo() br label %bb3 bb3: %v11 = add i32 %i0, %sum3 ret i32 %v11 } ; Branch or selects depends on another select. No CHR happens. ; Roughly, ; i0 = *i ; if (z == 0 & ((z != 1) ? pred : true)) { // Likely false ; foo() ; j0 = *j ; sum2 = ((i0 & 2) == j0) ? sum0 : (sum0 + 43) // Likely false ; sum3 = (i0 == sum2) ? sum2 : (sum0 + 43) // Likely false. This depends on the ; // previous select. ; foo() ; if ((i0 & 4) == 0) // Unbiased ; foo() ; return i0 + sum3 ; -> ; (no change) define i32 @test_chr_15(ptr %i, ptr %j, i32 %sum0, i1 %pred, i32 %z) !prof !14 { ; CHECK-LABEL: @test_chr_15( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[I0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[V0:%.*]] = icmp eq i32 [[Z:%.*]], 0 ; CHECK-NEXT: [[V3:%.*]] = select i1 [[V0]], i1 [[PRED:%.*]], i1 false ; CHECK-NEXT: br i1 [[V3]], label [[BB0:%.*]], label [[BB1:%.*]], !prof [[PROF16]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[J0:%.*]] = load i32, ptr [[J:%.*]], align 4 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[V9:%.*]] = and i32 [[I0]], 4 ; CHECK-NEXT: [[V10:%.*]] = icmp eq i32 [[V9]], 0 ; CHECK-NEXT: br i1 [[V10]], label [[BB3:%.*]], label [[BB2:%.*]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[V6:%.*]] = and i32 [[I0]], 2 ; CHECK-NEXT: [[V4:%.*]] = icmp eq i32 [[V6]], [[J0]] ; CHECK-NEXT: [[V8:%.*]] = add i32 [[SUM0:%.*]], 43 ; CHECK-NEXT: [[SUM2:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof [[PROF16]] ; CHECK-NEXT: [[V5:%.*]] = icmp eq i32 [[I0]], [[SUM2]] ; CHECK-NEXT: [[SUM3:%.*]] = select i1 [[V5]], i32 [[SUM2]], i32 [[V8]], !prof [[PROF16]] ; CHECK-NEXT: [[V11:%.*]] = add i32 [[I0]], [[SUM3]] ; CHECK-NEXT: ret i32 [[V11]] ; entry: %i0 = load i32, ptr %i %v0 = icmp eq i32 %z, 0 %v1 = icmp ne i32 %z, 1 %v2 = select i1 %v1, i1 %pred, i1 true, !prof !15 %v3 = and i1 %v0, %v2 br i1 %v3, label %bb0, label %bb1, !prof !15 bb0: call void @foo() br label %bb1 bb1: %j0 = load i32, ptr %j %v6 = and i32 %i0, 2 %v4 = icmp eq i32 %v6, %j0 %v8 = add i32 %sum0, 43 %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15 %v5 = icmp eq i32 %i0, %sum2 %sum3 = select i1 %v5, i32 %sum2, i32 %v8, !prof !15 call void @foo() %v9 = and i32 %i0, 4 %v10 = icmp eq i32 %v9, 0 br i1 %v10, label %bb3, label %bb2 bb2: call void @foo() br label %bb3 bb3: %v11 = add i32 %i0, %sum3 ret i32 %v11 } ; With an existing phi at the exit but a value (%v40) is both alive and is an ; operand to a phi at the exit block. ; Roughly, ; t0 = *i ; if ((t0 & 1) != 0) // Likely true ; foo() ; v40 = t0 + 44 ; if ((t0 & 2) != 0) // Likely true ; v41 = t0 + 99 ; foo() ; } ; v42 = phi v40, v41 ; return v42 + v40 ; -> ; t0 = *i ; if ((t0 & 3) == 3) // Likely true ; foo() ; v40 = t0 + 44 ; v41 = t0 + 99 ; foo() ; } else { ; if ((t0 & 1) != 0) // Likely true ; foo() ; v40_nc = t0 + 44 ; if ((t0 & 2) != 0) // Likely true ; v41_nc = t0 + 99 ; foo() ; } ; } ; t7 = phi v40, v40_nc ; v42 = phi v41, v41_nc ; v43 = v42 + t7 ; return v43 define i32 @test_chr_16(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_16( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[V40:%.*]] = add i32 [[TMP0]], 44 ; CHECK-NEXT: [[V41:%.*]] = add i32 [[TMP0]], 99 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[V40_NONCHR:%.*]] = add i32 [[TMP0]], 44 ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: [[V41_NONCHR:%.*]] = add i32 [[TMP0]], 99 ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[V40]], [[BB0]] ], [ [[V40_NONCHR]], [[BB2_NONCHR]] ], [ [[V40_NONCHR]], [[BB1_NONCHR]] ] ; CHECK-NEXT: [[V42:%.*]] = phi i32 [ [[V41]], [[BB0]] ], [ [[V41_NONCHR]], [[BB2_NONCHR]] ], [ [[V40_NONCHR]], [[BB1_NONCHR]] ] ; CHECK-NEXT: [[V43:%.*]] = add i32 [[V42]], [[TMP6]] ; CHECK-NEXT: ret i32 [[V43]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %v40 = add i32 %0, 44 %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !15 bb2: %v41 = add i32 %0, 99 call void @foo() br label %bb3 bb3: %v42 = phi i32 [ %v41, %bb2 ], [ %v40, %bb1 ] %v43 = add i32 %v42, %v40 ret i32 %v43 } ; Two consecutive regions have an entry in the middle of them. No CHR happens. ; Roughly, ; if ((i & 4) == 0) { ; if (!j) ; goto bb1 ; } else { ; t0 = (i & 1) ; if (t0 != 0) // Likely true ; foo() ; s = (i & 1) + i ; } ; bb1: ; p = phi i, t0, s ; if ((i & 2) != 0) // Likely true ; foo() ; q = p + 2 ; } ; r = phi p, q, i ; return r ; -> ; (no change) define i32 @test_chr_17(i32 %i, i1 %j) !prof !14 { ; CHECK-LABEL: @test_chr_17( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[V0:%.*]] = and i32 [[I:%.*]], 4 ; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0 ; CHECK-NEXT: br i1 [[V1]], label [[BBE:%.*]], label [[BBQ:%.*]] ; CHECK: bbq: ; CHECK-NEXT: br i1 [[J:%.*]], label [[BB3:%.*]], label [[BB1:%.*]] ; CHECK: bbe: ; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[I]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[TMP1]], label [[BB1]], label [[BB0:%.*]], !prof [[PROF16]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[S:%.*]] = add i32 [[TMP0]], [[I]] ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[I]], [[BBQ]] ], [ [[TMP0]], [[BBE]] ], [ [[S]], [[BB0]] ] ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[I]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 ; CHECK-NEXT: br i1 [[TMP3]], label [[BB3]], label [[BB2:%.*]], !prof [[PROF16]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: [[Q:%.*]] = add i32 [[P]], [[TMP2]] ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[P]], [[BB1]] ], [ [[Q]], [[BB2]] ], [ [[I]], [[BBQ]] ] ; CHECK-NEXT: ret i32 [[R]] ; entry: %v0 = and i32 %i, 4 %v1 = icmp eq i32 %v0, 0 br i1 %v1, label %bbe, label %bbq bbq: br i1 %j, label %bb3, label %bb1 bbe: %0 = and i32 %i, 1 %1 = icmp eq i32 %0, 0 br i1 %1, label %bb1, label %bb0, !prof !15 bb0: call void @foo() %s = add i32 %0, %i br label %bb1 bb1: %p = phi i32 [ %i, %bbq ], [ %0, %bbe ], [ %s, %bb0 ] %2 = and i32 %i, 2 %3 = icmp eq i32 %2, 0 br i1 %3, label %bb3, label %bb2, !prof !15 bb2: call void @foo() %q = add i32 %p, %2 br label %bb3 bb3: %r = phi i32 [ %p, %bb1 ], [ %q, %bb2 ], [ %i, %bbq ] ret i32 %r } ; Select + br, there's a loop and we need to update the user of an inserted phi ; at the entry block. This is a regression test for a bug that's fixed. ; Roughly, ; do { ; inc1 = phi inc2, 0 ; li = *i ; sum1 = sum0 + 42 ; sum2 = ((li & 1) == 0) ? sum0 : sum1 // Likely false ; inc2 = inc1 + 1 ; if ((li & 4) != 0) // Likely true ; sum3 = sum2 + 44 ; sum4 = phi sum1, sum3 ; } while (inc2 != 100) // Likely true (loop back) ; return sum4 ; -> ; do { ; inc1 = phi tmp2, 0 // The first operand needed to be updated ; li = *i ; sum1 = sum0 + 42 ; if ((li & 5) == 5) { // Likely true ; inc2 = inc1 + 1 ; sum3 = sum0 + 86 ; } else { ; inc2_nc = inc1 + 1 ; if ((li & 4) == 0) ; sum2_nc = ((li & 1) == 0) ? sum0 : sum1 ; sum3_nc = sum2_nc + 44 ; } ; tmp2 = phi inc2, in2c_nc ; sum4 = phi sum3, sum3_nc, sum1 ; } while (tmp2 != 100) ; return sum4 define i32 @test_chr_18(ptr %i, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_18( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[BB0:%.*]] ; CHECK: bb0: ; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ [[TMP2:%.*]], [[BB2:%.*]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[LI:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[LI_FR:%.*]] = freeze i32 [[LI]] ; CHECK-NEXT: [[SUM1:%.*]] = add i32 [[SUM0:%.*]], 42 ; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[LI_FR]], 5 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 5 ; CHECK-NEXT: br i1 [[TMP1]], label [[BB1:%.*]], label [[BB0_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb1: ; CHECK-NEXT: [[SUM3:%.*]] = add i32 [[SUM0]], 86 ; CHECK-NEXT: br label [[BB2]] ; CHECK: bb0.split.nonchr: ; CHECK-NEXT: [[A4_NONCHR:%.*]] = and i32 [[LI_FR]], 4 ; CHECK-NEXT: [[CMP4_NONCHR:%.*]] = icmp eq i32 [[A4_NONCHR]], 0 ; CHECK-NEXT: br i1 [[CMP4_NONCHR]], label [[BB2]], label [[BB1_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[A1:%.*]] = and i32 [[LI_FR]], 1 ; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp eq i32 [[A1]], 0 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[CMP1_NOT]], i32 [[SUM0]], i32 [[SUM1]], !prof [[PROF16]] ; CHECK-NEXT: [[SUM3_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], 44 ; CHECK-NEXT: br label [[BB2]] ; CHECK: bb2: ; CHECK-NEXT: [[SUM4:%.*]] = phi i32 [ [[SUM3]], [[BB1]] ], [ [[SUM1]], [[BB0_SPLIT_NONCHR]] ], [ [[SUM3_NONCHR]], [[BB1_NONCHR]] ] ; CHECK-NEXT: [[TMP2]] = add i32 [[INC1]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP2]], 100 ; CHECK-NEXT: br i1 [[CMP]], label [[BB3:%.*]], label [[BB0]], !prof [[PROF16]] ; CHECK: bb3: ; CHECK-NEXT: ret i32 [[SUM4]] ; entry: br label %bb0 bb0: %inc1 = phi i32 [ %inc2, %bb2 ], [ 0, %entry ] %li = load i32, ptr %i %a1 = and i32 %li, 1 %cmp1 = icmp eq i32 %a1, 0 %sum1 = add i32 %sum0, 42 %sum2 = select i1 %cmp1, i32 %sum0, i32 %sum1, !prof !15 %a4 = and i32 %li, 4 %cmp4 = icmp eq i32 %a4, 0 %inc2 = add i32 %inc1, 1 br i1 %cmp4, label %bb2, label %bb1, !prof !15 bb1: %sum3 = add i32 %sum2, 44 br label %bb2 bb2: %sum4 = phi i32 [ %sum1, %bb0 ], [ %sum3, %bb1 ] %cmp = icmp eq i32 %inc2, 100 br i1 %cmp, label %bb3, label %bb0, !prof !15 bb3: ret i32 %sum4 } ; Selects + Brs. Those share the condition value, which causes the ; targets/operands of the branch/select to be flipped. ; Roughly, ; t0 = *i ; if ((t0 & 255) != 0) { // Likely true ; sum1 = ((t0 & 1) == 0) ? sum0 : (sum0 + 42) // Likely false ; sum2 = ((t0 & 1) == 0) ? sum1 : (sum1 + 42) // Likely false ; if ((t0 & 1) != 0) { // Likely true ; sum3 = sum2 + 44 ; sum4 = ((t0 & 8) == 0) ? sum3 : (sum3 + 44) // Likely false ; } ; sum5 = phi sum2, sum4 ; } ; sum6 = phi sum0, sum5 ; return sum6 ; -> ; t0 = *i ; if ((t0 & 9) == 9) { // Likely true ; tmp3 = sum0 + 85 // Dead ; tmp4 = sum0 + 173 ; } else { ; if ((t0 & 255) != 0) { ; sum2_nc = ((t0 & 1) == 0) ? sum0 : (sum0 + 85) ; sum4_nc_v = ((t0 & 8) == 0) ? 44 : 88 ; sum4_nc = add sum2_nc + sum4_nc_v ; } ; } ; sum6 = phi tmp4, sum0, sum2_nc, sum4_nc ; return sum6 define i32 @test_chr_19(ptr %i, i32 %sum0) !prof !14 { ; CHECK-LABEL: @test_chr_19( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[DOTFR1:%.*]] = freeze i32 [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[DOTFR1]], 9 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 9 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85 ; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[SUM0]], 173 ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[DOTFR1]], 255 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP5]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[DOTFR1]], 1 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[SUM0]], 85 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[TMP7]], i32 [[SUM0]], i32 [[TMP8]], !prof [[PROF16]] ; CHECK-NEXT: [[TMP9:%.*]] = and i32 [[DOTFR1]], 8 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 0 ; CHECK-NEXT: [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP10]], i32 44, i32 88 ; CHECK-NEXT: [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]] ; CHECK-NEXT: [[SUM5_NONCHR:%.*]] = select i1 [[TMP7]], i32 [[SUM2_NONCHR]], i32 [[SUM4_NONCHR]], !prof [[PROF16]] ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[SUM6:%.*]] = phi i32 [ [[TMP4]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM5_NONCHR]], [[BB0_NONCHR]] ] ; CHECK-NEXT: ret i32 [[SUM6]] ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 255 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb3, label %bb0, !prof !15 bb0: %3 = and i32 %0, 1 %4 = icmp eq i32 %3, 0 %5 = add i32 %sum0, 42 %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15 %6 = add i32 %sum1, 43 %sum2 = select i1 %4, i32 %sum1, i32 %6, !prof !15 br i1 %4, label %bb2, label %bb1, !prof !15 bb1: %sum3 = add i32 %sum2, 44 %7 = and i32 %0, 8 %8 = icmp eq i32 %7, 0 %9 = add i32 %sum3, 44 %sum4 = select i1 %8, i32 %sum3, i32 %9, !prof !15 br label %bb2 bb2: %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ] br label %bb3 bb3: %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ] ret i32 %sum6 } ; Selects. The exit block, which belongs to the top-level region, has a select ; and causes the top-level region to be the outermost CHR scope with the ; subscope that includes the entry block with two selects. The outermost CHR ; scope doesn't see the selects in the entry block as the entry block is in the ; subscope and incorrectly sets the CHR hoist point to the branch rather than ; the first select in the entry block and causes the CHR'ed selects ("select i1 ; false...") to incorrectly position above the CHR branch. This is testing ; against a quirk of how the region analysis handles the entry block. ; Roughly, ; i0 = *i ; sum2 = ((i0 & 2) == 0) ? sum0 : (sum0 + 43) // Likely false ; sum3 = ((i0 & 4) == 0) ? sum2 : (sum2 + 44) // Likely false ; if (j) ; foo() ; i5 = *i ; v13 = (i5 == 44) ? i5 : sum3 ; return v13 ; -> ; i0 = *i ; if ((i0 & 6) != 6) { // Likely true ; v9 = sum0 + 87 ; if (j) ; foo() ; } else { ; sum2.nc = ((i0 & 2) == 0) ? sum0 : (sum0 + 43) ; sum3.nc = ((i0 & 4) == 0) ? sum2.nc : (sum2.nc + 44) ; if (j) ; foo() ; } ; t2 = phi v9, sum3.nc ; i5 = *i ; v13 = (i5 == 44) ? 44 : t2 ; return v13 define i32 @test_chr_20(ptr %i, i32 %sum0, i1 %j) !prof !14 { ; CHECK-LABEL: @test_chr_20( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[I0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[I0_FR:%.*]] = freeze i32 [[I0]] ; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[I0_FR]], 6 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 6 ; CHECK-NEXT: br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: entry.split: ; CHECK-NEXT: [[V9:%.*]] = add i32 [[SUM0:%.*]], 87 ; CHECK-NEXT: br i1 [[J:%.*]], label [[BB1:%.*]], label [[BB4:%.*]] ; CHECK: bb1: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB4]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[V8:%.*]] = add i32 [[SUM0]], 43 ; CHECK-NEXT: [[V3:%.*]] = and i32 [[I0_FR]], 2 ; CHECK-NEXT: [[V4_NOT:%.*]] = icmp eq i32 [[V3]], 0 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[V4_NOT]], i32 [[SUM0]], i32 [[V8]], !prof [[PROF16]] ; CHECK-NEXT: [[V6_NONCHR:%.*]] = and i32 [[I0_FR]], 4 ; CHECK-NEXT: [[V5_NONCHR:%.*]] = icmp eq i32 [[V6_NONCHR]], 0 ; CHECK-NEXT: [[V9_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], 44 ; CHECK-NEXT: [[SUM3_NONCHR:%.*]] = select i1 [[V5_NONCHR]], i32 [[SUM2_NONCHR]], i32 [[V9_NONCHR]], !prof [[PROF16]] ; CHECK-NEXT: br i1 [[J]], label [[BB1_NONCHR:%.*]], label [[BB4]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB4]] ; CHECK: bb4: ; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[V9]], [[BB1]] ], [ [[V9]], [[ENTRY_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB1_NONCHR]] ], [ [[SUM3_NONCHR]], [[ENTRY_SPLIT_NONCHR]] ] ; CHECK-NEXT: [[I5:%.*]] = load i32, ptr [[I]], align 4 ; CHECK-NEXT: [[V12:%.*]] = icmp eq i32 [[I5]], 44 ; CHECK-NEXT: [[V13:%.*]] = select i1 [[V12]], i32 44, i32 [[TMP2]], !prof [[PROF16]] ; CHECK-NEXT: ret i32 [[V13]] ; entry: %i0 = load i32, ptr %i %v3 = and i32 %i0, 2 %v4 = icmp eq i32 %v3, 0 %v8 = add i32 %sum0, 43 %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15 %v6 = and i32 %i0, 4 %v5 = icmp eq i32 %v6, 0 %v9 = add i32 %sum2, 44 %sum3 = select i1 %v5, i32 %sum2, i32 %v9, !prof !15 br i1 %j, label %bb1, label %bb4 bb1: call void @foo() br label %bb4 bb4: %i5 = load i32, ptr %i %v12 = icmp eq i32 %i5, 44 %v13 = select i1 %v12, i32 %i5, i32 %sum3, !prof !15 ret i32 %v13 } ; Test the case where two scopes share a common instruction to hoist (%cmp.i). ; Two scopes would hoist it to their hoist points, but since the outer scope ; hoists (entry/bb6-9) it first to its hoist point, it'd be wrong (causing bad ; IR) for the inner scope (bb1-4) to hoist the same instruction to its hoist ; point. ; Roughly, ; if (j != k) { ; if (i != 2) ; foo(); ; cmp.i = i == 86 ; if (!cmp.i) ; foo(); ; if (j != i) ; foo(); ; if (!cmp.i) ; foo(); ; } ; return 45; define i32 @test_chr_21(i64 %i, i64 %k, i64 %j) !prof !14 { ; CHECK-LABEL: @test_chr_21( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i64 [[J:%.*]], [[K:%.*]] ; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i64 [[J]], [[I:%.*]] ; CHECK-NEXT: [[CMP_I:%.*]] = icmp ne i64 [[I]], 86 ; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[CMP0]], i1 [[CMP3]], i1 false ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[CMP_I]], i1 false ; CHECK-NEXT: br i1 [[TMP1]], label [[BB1:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb1: ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i64 [[I]], 2 ; CHECK-NEXT: switch i64 [[I]], label [[BB2:%.*]] [ ; CHECK-NEXT: i64 2, label [[BB3_NONCHR2:%.*]] ; CHECK-NEXT: i64 86, label [[BB2_NONCHR1:%.*]] ; CHECK-NEXT: ], !prof [[PROF19:![0-9]+]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB7:%.*]] ; CHECK: bb2.nonchr1: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3_NONCHR2]] ; CHECK: bb3.nonchr2: ; CHECK-NEXT: br i1 [[CMP_I]], label [[BB4_NONCHR3:%.*]], label [[BB7]], !prof [[PROF18]] ; CHECK: bb4.nonchr3: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB7]] ; CHECK: bb7: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB10:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: br i1 [[CMP0]], label [[BB1_NONCHR:%.*]], label [[BB10]], !prof [[PROF18]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[CMP2_NONCHR:%.*]] = icmp eq i64 [[I]], 2 ; CHECK-NEXT: br i1 [[CMP2_NONCHR]], label [[BB3_NONCHR:%.*]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb3.nonchr: ; CHECK-NEXT: [[CMP_I_NONCHR:%.*]] = icmp eq i64 [[I]], 86 ; CHECK-NEXT: br i1 [[CMP_I_NONCHR]], label [[BB6_NONCHR:%.*]], label [[BB4_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb6.nonchr: ; CHECK-NEXT: [[CMP3_NONCHR:%.*]] = icmp eq i64 [[J]], [[I]] ; CHECK-NEXT: br i1 [[CMP3_NONCHR]], label [[BB8_NONCHR:%.*]], label [[BB7_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb8.nonchr: ; CHECK-NEXT: br i1 [[CMP_I_NONCHR]], label [[BB10]], label [[BB9_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb9.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB10]] ; CHECK: bb7.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB8_NONCHR]] ; CHECK: bb4.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB6_NONCHR]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3_NONCHR]] ; CHECK: bb10: ; CHECK-NEXT: ret i32 45 ; entry: %cmp0 = icmp eq i64 %j, %k br i1 %cmp0, label %bb10, label %bb1, !prof !15 bb1: %cmp2 = icmp eq i64 %i, 2 br i1 %cmp2, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: %cmp.i = icmp eq i64 %i, 86 br i1 %cmp.i, label %bb5, label %bb4, !prof !15 bb4: call void @foo() br label %bb5 bb5: br label %bb6 bb6: %cmp3 = icmp eq i64 %j, %i br i1 %cmp3, label %bb8, label %bb7, !prof !15 bb7: call void @foo() br label %bb8 bb8: br i1 %cmp.i, label %bb10, label %bb9, !prof !15 bb9: call void @foo() br label %bb10 bb10: ret i32 45 } ; Test a case with a really long use-def chains. This test checks that it's not ; really slow and doesn't appear to be hanging. define i64 @test_chr_22(i1 %i, ptr %j, i64 %v0) !prof !14 { ; CHECK-LABEL: @test_chr_22( ; CHECK-NEXT: bb0: ; CHECK-NEXT: [[V0_FR:%.*]] = freeze i64 [[V0:%.*]] ; CHECK-NEXT: [[REASS_ADD:%.*]] = shl i64 [[V0_FR]], 1 ; CHECK-NEXT: [[V2:%.*]] = add i64 [[REASS_ADD]], 3 ; CHECK-NEXT: [[C1:%.*]] = icmp slt i64 [[V2]], 100 ; CHECK-NEXT: br i1 [[C1]], label [[BB0_SPLIT:%.*]], label [[BB0_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: common.ret: ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i64 [ 99, [[BB0_SPLIT]] ], [ 99, [[BB0_SPLIT_NONCHR]] ] ; CHECK-NEXT: ret i64 [[COMMON_RET_OP]] ; CHECK: bb0.split: ; CHECK-NEXT: [[V299:%.*]] = mul i64 [[V2]], 7860086430977039991 ; CHECK-NEXT: store i64 [[V299]], ptr [[J:%.*]], align 4 ; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: bb0.split.nonchr: ; CHECK-NEXT: [[V299_NONCHR:%.*]] = mul i64 [[V2]], 7860086430977039991 ; CHECK-NEXT: store i64 [[V299_NONCHR]], ptr [[J]], align 4 ; CHECK-NEXT: br label [[COMMON_RET]] ; bb0: %v1 = add i64 %v0, 3 %v2 = add i64 %v1, %v0 %c1 = icmp sgt i64 %v2, 99 %v3 = select i1 %c1, i64 %v1, i64 %v2, !prof !15 %v4 = add i64 %v2, %v2 %v5 = add i64 %v4, %v2 %v6 = add i64 %v5, %v4 %v7 = add i64 %v6, %v5 %v8 = add i64 %v7, %v6 %v9 = add i64 %v8, %v7 %v10 = add i64 %v9, %v8 %v11 = add i64 %v10, %v9 %v12 = add i64 %v11, %v10 %v13 = add i64 %v12, %v11 %v14 = add i64 %v13, %v12 %v15 = add i64 %v14, %v13 %v16 = add i64 %v15, %v14 %v17 = add i64 %v16, %v15 %v18 = add i64 %v17, %v16 %v19 = add i64 %v18, %v17 %v20 = add i64 %v19, %v18 %v21 = add i64 %v20, %v19 %v22 = add i64 %v21, %v20 %v23 = add i64 %v22, %v21 %v24 = add i64 %v23, %v22 %v25 = add i64 %v24, %v23 %v26 = add i64 %v25, %v24 %v27 = add i64 %v26, %v25 %v28 = add i64 %v27, %v26 %v29 = add i64 %v28, %v27 %v30 = add i64 %v29, %v28 %v31 = add i64 %v30, %v29 %v32 = add i64 %v31, %v30 %v33 = add i64 %v32, %v31 %v34 = add i64 %v33, %v32 %v35 = add i64 %v34, %v33 %v36 = add i64 %v35, %v34 %v37 = add i64 %v36, %v35 %v38 = add i64 %v37, %v36 %v39 = add i64 %v38, %v37 %v40 = add i64 %v39, %v38 %v41 = add i64 %v40, %v39 %v42 = add i64 %v41, %v40 %v43 = add i64 %v42, %v41 %v44 = add i64 %v43, %v42 %v45 = add i64 %v44, %v43 %v46 = add i64 %v45, %v44 %v47 = add i64 %v46, %v45 %v48 = add i64 %v47, %v46 %v49 = add i64 %v48, %v47 %v50 = add i64 %v49, %v48 %v51 = add i64 %v50, %v49 %v52 = add i64 %v51, %v50 %v53 = add i64 %v52, %v51 %v54 = add i64 %v53, %v52 %v55 = add i64 %v54, %v53 %v56 = add i64 %v55, %v54 %v57 = add i64 %v56, %v55 %v58 = add i64 %v57, %v56 %v59 = add i64 %v58, %v57 %v60 = add i64 %v59, %v58 %v61 = add i64 %v60, %v59 %v62 = add i64 %v61, %v60 %v63 = add i64 %v62, %v61 %v64 = add i64 %v63, %v62 %v65 = add i64 %v64, %v63 %v66 = add i64 %v65, %v64 %v67 = add i64 %v66, %v65 %v68 = add i64 %v67, %v66 %v69 = add i64 %v68, %v67 %v70 = add i64 %v69, %v68 %v71 = add i64 %v70, %v69 %v72 = add i64 %v71, %v70 %v73 = add i64 %v72, %v71 %v74 = add i64 %v73, %v72 %v75 = add i64 %v74, %v73 %v76 = add i64 %v75, %v74 %v77 = add i64 %v76, %v75 %v78 = add i64 %v77, %v76 %v79 = add i64 %v78, %v77 %v80 = add i64 %v79, %v78 %v81 = add i64 %v80, %v79 %v82 = add i64 %v81, %v80 %v83 = add i64 %v82, %v81 %v84 = add i64 %v83, %v82 %v85 = add i64 %v84, %v83 %v86 = add i64 %v85, %v84 %v87 = add i64 %v86, %v85 %v88 = add i64 %v87, %v86 %v89 = add i64 %v88, %v87 %v90 = add i64 %v89, %v88 %v91 = add i64 %v90, %v89 %v92 = add i64 %v91, %v90 %v93 = add i64 %v92, %v91 %v94 = add i64 %v93, %v92 %v95 = add i64 %v94, %v93 %v96 = add i64 %v95, %v94 %v97 = add i64 %v96, %v95 %v98 = add i64 %v97, %v96 %v99 = add i64 %v98, %v97 %v100 = add i64 %v99, %v98 %v101 = add i64 %v100, %v99 %v102 = add i64 %v101, %v100 %v103 = add i64 %v102, %v101 %v104 = add i64 %v103, %v102 %v105 = add i64 %v104, %v103 %v106 = add i64 %v105, %v104 %v107 = add i64 %v106, %v105 %v108 = add i64 %v107, %v106 %v109 = add i64 %v108, %v107 %v110 = add i64 %v109, %v108 %v111 = add i64 %v110, %v109 %v112 = add i64 %v111, %v110 %v113 = add i64 %v112, %v111 %v114 = add i64 %v113, %v112 %v115 = add i64 %v114, %v113 %v116 = add i64 %v115, %v114 %v117 = add i64 %v116, %v115 %v118 = add i64 %v117, %v116 %v119 = add i64 %v118, %v117 %v120 = add i64 %v119, %v118 %v121 = add i64 %v120, %v119 %v122 = add i64 %v121, %v120 %v123 = add i64 %v122, %v121 %v124 = add i64 %v123, %v122 %v125 = add i64 %v124, %v123 %v126 = add i64 %v125, %v124 %v127 = add i64 %v126, %v125 %v128 = add i64 %v127, %v126 %v129 = add i64 %v128, %v127 %v130 = add i64 %v129, %v128 %v131 = add i64 %v130, %v129 %v132 = add i64 %v131, %v130 %v133 = add i64 %v132, %v131 %v134 = add i64 %v133, %v132 %v135 = add i64 %v134, %v133 %v136 = add i64 %v135, %v134 %v137 = add i64 %v136, %v135 %v138 = add i64 %v137, %v136 %v139 = add i64 %v138, %v137 %v140 = add i64 %v139, %v138 %v141 = add i64 %v140, %v139 %v142 = add i64 %v141, %v140 %v143 = add i64 %v142, %v141 %v144 = add i64 %v143, %v142 %v145 = add i64 %v144, %v143 %v146 = add i64 %v145, %v144 %v147 = add i64 %v146, %v145 %v148 = add i64 %v147, %v146 %v149 = add i64 %v148, %v147 %v150 = add i64 %v149, %v148 %v151 = add i64 %v150, %v149 %v152 = add i64 %v151, %v150 %v153 = add i64 %v152, %v151 %v154 = add i64 %v153, %v152 %v155 = add i64 %v154, %v153 %v156 = add i64 %v155, %v154 %v157 = add i64 %v156, %v155 %v158 = add i64 %v157, %v156 %v159 = add i64 %v158, %v157 %v160 = add i64 %v159, %v158 %v161 = add i64 %v160, %v159 %v162 = add i64 %v161, %v160 %v163 = add i64 %v162, %v161 %v164 = add i64 %v163, %v162 %v165 = add i64 %v164, %v163 %v166 = add i64 %v165, %v164 %v167 = add i64 %v166, %v165 %v168 = add i64 %v167, %v166 %v169 = add i64 %v168, %v167 %v170 = add i64 %v169, %v168 %v171 = add i64 %v170, %v169 %v172 = add i64 %v171, %v170 %v173 = add i64 %v172, %v171 %v174 = add i64 %v173, %v172 %v175 = add i64 %v174, %v173 %v176 = add i64 %v175, %v174 %v177 = add i64 %v176, %v175 %v178 = add i64 %v177, %v176 %v179 = add i64 %v178, %v177 %v180 = add i64 %v179, %v178 %v181 = add i64 %v180, %v179 %v182 = add i64 %v181, %v180 %v183 = add i64 %v182, %v181 %v184 = add i64 %v183, %v182 %v185 = add i64 %v184, %v183 %v186 = add i64 %v185, %v184 %v187 = add i64 %v186, %v185 %v188 = add i64 %v187, %v186 %v189 = add i64 %v188, %v187 %v190 = add i64 %v189, %v188 %v191 = add i64 %v190, %v189 %v192 = add i64 %v191, %v190 %v193 = add i64 %v192, %v191 %v194 = add i64 %v193, %v192 %v195 = add i64 %v194, %v193 %v196 = add i64 %v195, %v194 %v197 = add i64 %v196, %v195 %v198 = add i64 %v197, %v196 %v199 = add i64 %v198, %v197 %v200 = add i64 %v199, %v198 %v201 = add i64 %v200, %v199 %v202 = add i64 %v201, %v200 %v203 = add i64 %v202, %v201 %v204 = add i64 %v203, %v202 %v205 = add i64 %v204, %v203 %v206 = add i64 %v205, %v204 %v207 = add i64 %v206, %v205 %v208 = add i64 %v207, %v206 %v209 = add i64 %v208, %v207 %v210 = add i64 %v209, %v208 %v211 = add i64 %v210, %v209 %v212 = add i64 %v211, %v210 %v213 = add i64 %v212, %v211 %v214 = add i64 %v213, %v212 %v215 = add i64 %v214, %v213 %v216 = add i64 %v215, %v214 %v217 = add i64 %v216, %v215 %v218 = add i64 %v217, %v216 %v219 = add i64 %v218, %v217 %v220 = add i64 %v219, %v218 %v221 = add i64 %v220, %v219 %v222 = add i64 %v221, %v220 %v223 = add i64 %v222, %v221 %v224 = add i64 %v223, %v222 %v225 = add i64 %v224, %v223 %v226 = add i64 %v225, %v224 %v227 = add i64 %v226, %v225 %v228 = add i64 %v227, %v226 %v229 = add i64 %v228, %v227 %v230 = add i64 %v229, %v228 %v231 = add i64 %v230, %v229 %v232 = add i64 %v231, %v230 %v233 = add i64 %v232, %v231 %v234 = add i64 %v233, %v232 %v235 = add i64 %v234, %v233 %v236 = add i64 %v235, %v234 %v237 = add i64 %v236, %v235 %v238 = add i64 %v237, %v236 %v239 = add i64 %v238, %v237 %v240 = add i64 %v239, %v238 %v241 = add i64 %v240, %v239 %v242 = add i64 %v241, %v240 %v243 = add i64 %v242, %v241 %v244 = add i64 %v243, %v242 %v245 = add i64 %v244, %v243 %v246 = add i64 %v245, %v244 %v247 = add i64 %v246, %v245 %v248 = add i64 %v247, %v246 %v249 = add i64 %v248, %v247 %v250 = add i64 %v249, %v248 %v251 = add i64 %v250, %v249 %v252 = add i64 %v251, %v250 %v253 = add i64 %v252, %v251 %v254 = add i64 %v253, %v252 %v255 = add i64 %v254, %v253 %v256 = add i64 %v255, %v254 %v257 = add i64 %v256, %v255 %v258 = add i64 %v257, %v256 %v259 = add i64 %v258, %v257 %v260 = add i64 %v259, %v258 %v261 = add i64 %v260, %v259 %v262 = add i64 %v261, %v260 %v263 = add i64 %v262, %v261 %v264 = add i64 %v263, %v262 %v265 = add i64 %v264, %v263 %v266 = add i64 %v265, %v264 %v267 = add i64 %v266, %v265 %v268 = add i64 %v267, %v266 %v269 = add i64 %v268, %v267 %v270 = add i64 %v269, %v268 %v271 = add i64 %v270, %v269 %v272 = add i64 %v271, %v270 %v273 = add i64 %v272, %v271 %v274 = add i64 %v273, %v272 %v275 = add i64 %v274, %v273 %v276 = add i64 %v275, %v274 %v277 = add i64 %v276, %v275 %v278 = add i64 %v277, %v276 %v279 = add i64 %v278, %v277 %v280 = add i64 %v279, %v278 %v281 = add i64 %v280, %v279 %v282 = add i64 %v281, %v280 %v283 = add i64 %v282, %v281 %v284 = add i64 %v283, %v282 %v285 = add i64 %v284, %v283 %v286 = add i64 %v285, %v284 %v287 = add i64 %v286, %v285 %v288 = add i64 %v287, %v286 %v289 = add i64 %v288, %v287 %v290 = add i64 %v289, %v288 %v291 = add i64 %v290, %v289 %v292 = add i64 %v291, %v290 %v293 = add i64 %v292, %v291 %v294 = add i64 %v293, %v292 %v295 = add i64 %v294, %v293 %v296 = add i64 %v295, %v294 %v297 = add i64 %v296, %v295 %v298 = add i64 %v297, %v296 %v299 = add i64 %v298, %v297 %v300 = add i64 %v299, %v298 %v301 = icmp eq i64 %v300, 100 %v302 = select i1 %v301, i64 %v298, i64 %v299, !prof !15 store i64 %v302, ptr %j ret i64 99 } ; Test a case with a really long use-def chains. This test checks that it's not ; really slow and doesn't appear to be hanging. This is different from ; test_chr_22 in that it has nested control structures (multiple scopes) and ; covers additional code. define i64 @test_chr_23(i64 %v0) !prof !14 { ; CHECK-LABEL: @test_chr_23( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[V0:%.*]], 50 ; CHECK-NEXT: [[V10_NOT:%.*]] = icmp eq i64 [[TMP0]], -50 ; CHECK-NEXT: ret i64 99 ; entry: %v1 = add i64 %v0, 3 %v2 = add i64 %v1, %v1 %v3 = add i64 %v2, %v1 %v4 = add i64 %v2, %v3 %v5 = add i64 %v4, %v2 %v6 = add i64 %v5, %v4 %v7 = add i64 %v6, %v5 %v8 = add i64 %v7, %v6 %v9 = add i64 %v8, %v7 %v10 = icmp eq i64 %v9, 100 br i1 %v10, label %body, label %end, !prof !15 body: %v1_0 = add i64 %v9, 3 %v2_0 = add i64 %v1_0, %v1_0 %v3_0 = add i64 %v2_0, %v1_0 %v4_0 = add i64 %v2_0, %v3_0 %v5_0 = add i64 %v4_0, %v2_0 %v6_0 = add i64 %v5_0, %v4_0 %v7_0 = add i64 %v6_0, %v5_0 %v8_0 = add i64 %v7_0, %v6_0 %v9_0 = add i64 %v8_0, %v7_0 %v10_0 = icmp eq i64 %v9_0, 100 br i1 %v10_0, label %body.1, label %end, !prof !15 body.1: %v1_1 = add i64 %v9_0, 3 %v2_1 = add i64 %v1_1, %v1_1 %v3_1 = add i64 %v2_1, %v1_1 %v4_1 = add i64 %v2_1, %v3_1 %v5_1 = add i64 %v4_1, %v2_1 %v6_1 = add i64 %v5_1, %v4_1 %v7_1 = add i64 %v6_1, %v5_1 %v8_1 = add i64 %v7_1, %v6_1 %v9_1 = add i64 %v8_1, %v7_1 %v10_1 = icmp eq i64 %v9_1, 100 br i1 %v10_1, label %body.2, label %end, !prof !15 body.2: %v1_2 = add i64 %v9_1, 3 %v2_2 = add i64 %v1_2, %v1_2 %v3_2 = add i64 %v2_2, %v1_2 %v4_2 = add i64 %v2_2, %v3_2 %v5_2 = add i64 %v4_2, %v2_2 %v6_2 = add i64 %v5_2, %v4_2 %v7_2 = add i64 %v6_2, %v5_2 %v8_2 = add i64 %v7_2, %v6_2 %v9_2 = add i64 %v8_2, %v7_2 %v10_2 = icmp eq i64 %v9_2, 100 br i1 %v10_2, label %body.3, label %end, !prof !15 body.3: %v1_3 = add i64 %v9_2, 3 %v2_3 = add i64 %v1_3, %v1_3 %v3_3 = add i64 %v2_3, %v1_3 %v4_3 = add i64 %v2_3, %v3_3 %v5_3 = add i64 %v4_3, %v2_3 %v6_3 = add i64 %v5_3, %v4_3 %v7_3 = add i64 %v6_3, %v5_3 %v8_3 = add i64 %v7_3, %v6_3 %v9_3 = add i64 %v8_3, %v7_3 %v10_3 = icmp eq i64 %v9_3, 100 br i1 %v10_3, label %body.4, label %end, !prof !15 body.4: %v1_4 = add i64 %v9_3, 3 %v2_4 = add i64 %v1_4, %v1_4 %v3_4 = add i64 %v2_4, %v1_4 %v4_4 = add i64 %v2_4, %v3_4 %v5_4 = add i64 %v4_4, %v2_4 %v6_4 = add i64 %v5_4, %v4_4 %v7_4 = add i64 %v6_4, %v5_4 %v8_4 = add i64 %v7_4, %v6_4 %v9_4 = add i64 %v8_4, %v7_4 %v10_4 = icmp eq i64 %v9_4, 100 br i1 %v10_4, label %body.5, label %end, !prof !15 body.5: %v1_5 = add i64 %v9_4, 3 %v2_5 = add i64 %v1_5, %v1_5 %v3_5 = add i64 %v2_5, %v1_5 %v4_5 = add i64 %v2_5, %v3_5 %v5_5 = add i64 %v4_5, %v2_5 %v6_5 = add i64 %v5_5, %v4_5 %v7_5 = add i64 %v6_5, %v5_5 %v8_5 = add i64 %v7_5, %v6_5 %v9_5 = add i64 %v8_5, %v7_5 %v10_5 = icmp eq i64 %v9_5, 100 br i1 %v10_5, label %body.6, label %end, !prof !15 body.6: %v1_6 = add i64 %v9_5, 3 %v2_6 = add i64 %v1_6, %v1_6 %v3_6 = add i64 %v2_6, %v1_6 %v4_6 = add i64 %v2_6, %v3_6 %v5_6 = add i64 %v4_6, %v2_6 %v6_6 = add i64 %v5_6, %v4_6 %v7_6 = add i64 %v6_6, %v5_6 %v8_6 = add i64 %v7_6, %v6_6 %v9_6 = add i64 %v8_6, %v7_6 %v10_6 = icmp eq i64 %v9_6, 100 br i1 %v10_6, label %body.7, label %end, !prof !15 body.7: %v1_7 = add i64 %v9_6, 3 %v2_7 = add i64 %v1_7, %v1_7 %v3_7 = add i64 %v2_7, %v1_7 %v4_7 = add i64 %v2_7, %v3_7 %v5_7 = add i64 %v4_7, %v2_7 %v6_7 = add i64 %v5_7, %v4_7 %v7_7 = add i64 %v6_7, %v5_7 %v8_7 = add i64 %v7_7, %v6_7 %v9_7 = add i64 %v8_7, %v7_7 %v10_7 = icmp eq i64 %v9_7, 100 br i1 %v10_7, label %body.8, label %end, !prof !15 body.8: %v1_8 = add i64 %v9_7, 3 %v2_8 = add i64 %v1_8, %v1_8 %v3_8 = add i64 %v2_8, %v1_8 %v4_8 = add i64 %v2_8, %v3_8 %v5_8 = add i64 %v4_8, %v2_8 %v6_8 = add i64 %v5_8, %v4_8 %v7_8 = add i64 %v6_8, %v5_8 %v8_8 = add i64 %v7_8, %v6_8 %v9_8 = add i64 %v8_8, %v7_8 %v10_8 = icmp eq i64 %v9_8, 100 br i1 %v10_8, label %body.9, label %end, !prof !15 body.9: %v1_9 = add i64 %v9_8, 3 %v2_9 = add i64 %v1_9, %v1_9 %v3_9 = add i64 %v2_9, %v1_9 %v4_9 = add i64 %v2_9, %v3_9 %v5_9 = add i64 %v4_9, %v2_9 %v6_9 = add i64 %v5_9, %v4_9 %v7_9 = add i64 %v6_9, %v5_9 %v8_9 = add i64 %v7_9, %v6_9 %v9_9 = add i64 %v8_9, %v7_9 br label %end end: ret i64 99 } ; Test to not crash upon a 0:0 branch_weight metadata. define void @test_chr_24(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_24( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF20:![0-9]+]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[TMP4]], label [[BB3:%.*]], label [[BB2:%.*]], !prof [[PROF20]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !17 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !17 bb2: call void @foo() br label %bb3 bb3: ret void } ; Test that chr will skip this function when addresses are taken on basic blocks. @gototable1 = weak_odr dso_local local_unnamed_addr constant [2 x ptr] [ptr blockaddress(@test_chr_with_bbs_address_taken1, %bb3), ptr blockaddress(@test_chr_with_bbs_address_taken1, %bb3)] define void @test_chr_with_bbs_address_taken1(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_with_bbs_address_taken1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF16]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[TMP4]], label [[BB4:%.*]], label [[BB2:%.*]], !prof [[PROF16]] ; CHECK: bb2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB4]] ; CHECK: bb4: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb4, label %bb2, !prof !15 bb2: call void @foo() indirectbr ptr %i, [label %bb3, label %bb3] bb3: br label %bb4 bb4: ret void } ; Test that chr will still optimize the first 2 regions, ; but will skip the last one due to basic blocks have address taken. @gototable2 = weak_odr dso_local local_unnamed_addr constant [2 x ptr] [ptr blockaddress(@test_chr_with_bbs_address_taken2, %bb5), ptr blockaddress(@test_chr_with_bbs_address_taken2, %bb5)] define void @test_chr_with_bbs_address_taken2(ptr %i) !prof !14 { ; CHECK-LABEL: @test_chr_with_bbs_address_taken2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3 ; CHECK-NEXT: br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB6:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 1 ; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[DOTNOT]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb0.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB1_NONCHR]] ; CHECK: bb1.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 2 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB6]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[BB6]] ; CHECK: bb6: ; CHECK-NEXT: ret void ; entry: %0 = load i32, ptr %i %1 = and i32 %0, 1 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb1, label %bb0, !prof !15 bb0: call void @foo() br label %bb1 bb1: %3 = and i32 %0, 2 %4 = icmp eq i32 %3, 0 br i1 %4, label %bb3, label %bb2, !prof !15 bb2: call void @foo() br label %bb3 bb3: %5 = and i32 %0, 2 %6 = icmp eq i32 %5, 0 br i1 %6, label %bb6, label %bb4, !prof !15 bb4: indirectbr ptr %i, [label %bb5, label %bb5] bb5: br label %bb6 bb6: ret void } !llvm.module.flags = !{!0} !0 = !{i32 1, !"ProfileSummary", !1} !1 = !{!2, !3, !4, !5, !6, !7, !8, !9} !2 = !{!"ProfileFormat", !"InstrProf"} !3 = !{!"TotalCount", i64 10000} !4 = !{!"MaxCount", i64 10} !5 = !{!"MaxInternalCount", i64 1} !6 = !{!"MaxFunctionCount", i64 1000} !7 = !{!"NumCounts", i64 3} !8 = !{!"NumFunctions", i64 3} !9 = !{!"DetailedSummary", !10} !10 = !{!11, !12, !13} !11 = !{i32 10000, i64 100, i32 1} !12 = !{i32 999000, i64 100, i32 1} !13 = !{i32 999999, i64 1, i32 2} !14 = !{!"function_entry_count", i64 100} !15 = !{!"branch_weights", i32 0, i32 1} !16 = !{!"branch_weights", i32 1, i32 1} !17 = !{!"branch_weights", i32 0, i32 0} ; CHECK: !15 = !{!"branch_weights", i32 1000, i32 0} ; CHECK: !16 = !{!"branch_weights", i32 0, i32 1} ; CHECK: !17 = !{!"branch_weights", i32 1, i32 1} ; CHECK: !18 = !{!"branch_weights", i32 1, i32 0}