1913 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			1913 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			LLVM
		
	
	
	
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 | |
| ; RUN: opt < %s -chr -instcombine -simplifycfg -S | FileCheck %s
 | |
| ; RUN: opt < %s -passes='require<profile-summary>,function(chr,instcombine,simplify-cfg)' -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(i32* %i) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_1(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; 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:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; 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 !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_1_1(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; 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:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; 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 [[BB2_NONCHR:%.*]], label [[BB3_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    call void @bar()
 | |
| ; CHECK-NEXT:    br label [[BB3_NONCHR]]
 | |
| ; CHECK:       bb3.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 4
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP8]], label [[BB5]], label [[BB4_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb4.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB5]]
 | |
| ; CHECK:       bb5:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_2(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; 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:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP4]], label [[BB4]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 1
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP6]], label [[BB2_NONCHR:%.*]], label [[BB1_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 2
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP8]], label [[BB4]], label [[BB3_NONCHR:%.*]], !prof !16
 | |
| ; 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, i32* %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(i32* %i) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_3(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; 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:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; 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 !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* [[I]], align 4
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP7]], 12
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 12
 | |
| ; CHECK-NEXT:    br i1 [[TMP9]], label [[BB4:%.*]], label [[BB3_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; CHECK:       bb4:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB7:%.*]]
 | |
| ; CHECK:       bb3.split.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP7]], 4
 | |
| ; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP11]], label [[BB5_NONCHR:%.*]], label [[BB4_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb4.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB5_NONCHR]]
 | |
| ; CHECK:       bb5.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP12:%.*]] = and i32 [[TMP7]], 8
 | |
| ; CHECK-NEXT:    [[TMP13:%.*]] = icmp eq i32 [[TMP12]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP13]], label [[BB7]], label [[BB6_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb6.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB7]]
 | |
| ; CHECK:       bb7:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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, i32* %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(i32* %i, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_4(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
 | |
| ; CHECK-NEXT:    br i1 [[TMP2]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; CHECK:       entry.split:
 | |
| ; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85
 | |
| ; CHECK-NEXT:    ret i32 [[TMP3]]
 | |
| ; CHECK:       entry.split.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[SUM0]], 42
 | |
| ; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 1
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 | |
| ; CHECK-NEXT:    [[SUM1_NONCHR:%.*]] = select i1 [[TMP6]], i32 [[SUM0]], i32 [[TMP4]], !prof !16
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 2
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = add i32 [[SUM1_NONCHR]], 43
 | |
| ; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP8]], i32 [[SUM1_NONCHR]], i32 [[TMP9]], !prof !16
 | |
| ; CHECK-NEXT:    ret i32 [[SUM2_NONCHR]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_5(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 15
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 15
 | |
| ; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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 [[TMP0]], 255
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 1
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = add i32 [[SUM0]], 42
 | |
| ; CHECK-NEXT:    [[SUM1_NONCHR:%.*]] = select i1 [[TMP8]], i32 [[SUM0]], i32 [[TMP9]], !prof !16
 | |
| ; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP0]], 2
 | |
| ; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
 | |
| ; CHECK-NEXT:    [[TMP12:%.*]] = add i32 [[SUM1_NONCHR]], 43
 | |
| ; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP11]], i32 [[SUM1_NONCHR]], i32 [[TMP12]], !prof !16
 | |
| ; CHECK-NEXT:    [[TMP13:%.*]] = and i32 [[TMP0]], 4
 | |
| ; CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i32 [[TMP13]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP14]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP15:%.*]] = and i32 [[TMP0]], 8
 | |
| ; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP16]], i32 44, i32 88, !prof !16
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[TMP4]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
 | |
| ; CHECK-NEXT:    ret i32 [[SUM6]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_5_1(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[SUM0:%.*]], 4
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
 | |
| ; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 11
 | |
| ; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 11
 | |
| ; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP2]]
 | |
| ; CHECK-NEXT:    br i1 [[TMP5]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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 [[TMP0]], 255
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP9]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP0]], 1
 | |
| ; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
 | |
| ; CHECK-NEXT:    [[TMP12:%.*]] = add i32 [[SUM0]], 42
 | |
| ; CHECK-NEXT:    [[SUM1_NONCHR:%.*]] = select i1 [[TMP11]], i32 [[SUM0]], i32 [[TMP12]], !prof !16
 | |
| ; CHECK-NEXT:    [[TMP13:%.*]] = and i32 [[TMP0]], 2
 | |
| ; CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i32 [[TMP13]], 0
 | |
| ; CHECK-NEXT:    [[TMP15:%.*]] = add i32 [[SUM1_NONCHR]], 43
 | |
| ; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP14]], i32 [[SUM1_NONCHR]], i32 [[TMP15]], !prof !16
 | |
| ; CHECK-NEXT:    [[TMP16:%.*]] = and i32 [[SUM0]], 4
 | |
| ; CHECK-NEXT:    [[TMP17:%.*]] = icmp eq i32 [[TMP16]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP17]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP18:%.*]] = and i32 [[TMP0]], 8
 | |
| ; CHECK-NEXT:    [[TMP19:%.*]] = icmp eq i32 [[TMP18]], 0
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP19]], i32 44, i32 88, !prof !16
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[TMP7]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
 | |
| ; CHECK-NEXT:    ret i32 [[SUM6]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i, i32* %j, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_6(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[V9:%.*]] = and i32 [[J0]], 4
 | |
| ; CHECK-NEXT:    [[V10:%.*]] = icmp ne i32 [[V9]], 0
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[I0]], 10
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 10
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[V10]]
 | |
| ; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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]], 255
 | |
| ; CHECK-NEXT:    [[V2:%.*]] = icmp eq i32 [[V1]], 0
 | |
| ; CHECK-NEXT:    br i1 [[V2]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    [[V3_NONCHR:%.*]] = and i32 [[I0]], 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 !16
 | |
| ; CHECK-NEXT:    [[V9_NONCHR:%.*]] = and i32 [[J0]], 4
 | |
| ; CHECK-NEXT:    [[V10_NONCHR:%.*]] = icmp eq i32 [[V9_NONCHR]], 0
 | |
| ; CHECK-NEXT:    br i1 [[V10_NONCHR]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[V11_NONCHR:%.*]] = and i32 [[I0]], 8
 | |
| ; CHECK-NEXT:    [[V12_NONCHR:%.*]] = icmp eq i32 [[V11_NONCHR]], 0
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[V12_NONCHR]], i32 44, i32 88, !prof !16
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[V13]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
 | |
| ; CHECK-NEXT:    ret i32 [[SUM6]]
 | |
| ;
 | |
| entry:
 | |
|   %i0 = load i32, i32* %i
 | |
|   %j0 = load i32, i32* %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(i32* %i, i32* %j, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_7(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[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 !16
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[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 !16
 | |
| ; 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, i32* %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, i32* %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(i32* %i, i32* %j, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_7_1(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[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 !16
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[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 !15
 | |
| ; 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:%.*]] = icmp eq i32 [[V9]], 0
 | |
| ; CHECK-NEXT:    br i1 [[V10]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; 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 !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    ret i32 [[SUM2]]
 | |
| ;
 | |
| entry:
 | |
|   %i0 = load i32, i32* %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, i32* %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(i32* %i) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_8(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !17
 | |
| ; 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 !17
 | |
| ; CHECK:       bb2:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i, i32* %j) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_9(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; CHECK:       bb0:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[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:    [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP5]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB1_NONCHR]]
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; 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 !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[J]], align 4
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP0]], [[BB1_NONCHR]] ], [ [[TMP8]], [[BB2_NONCHR]] ]
 | |
| ; CHECK-NEXT:    ret i32 [[TMP9]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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, i32* %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(i32* %i, i32* %j) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_10(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; CHECK:       bb0:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[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:    [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP5]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB1_NONCHR]]
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* [[J]], align 4
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 2
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP8]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP6]], [[BB2_NONCHR]] ], [ [[TMP6]], [[BB1_NONCHR]] ]
 | |
| ; CHECK-NEXT:    [[TMP10:%.*]] = mul i32 [[TMP9]], 42
 | |
| ; CHECK-NEXT:    [[TMP11:%.*]] = add i32 [[TMP9]], -99
 | |
| ; CHECK-NEXT:    [[TMP12:%.*]] = add i32 [[TMP10]], [[TMP11]]
 | |
| ; CHECK-NEXT:    ret i32 [[TMP12]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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, i32* %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(i32* %i, i32 %x) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_11(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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:%.*]] = and i1 [[TMP2]], [[CMP18]]
 | |
| ; CHECK-NEXT:    br i1 [[TMP3]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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 !18
 | |
| ; 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 !16
 | |
| ; CHECK:       bb2.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    ret void
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_12(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 255
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP2]], label [[BB3:%.*]], label [[BB0:%.*]], !prof !16
 | |
| ; CHECK:       bb0:
 | |
| ; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 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 !16
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = and i32 [[TMP0]], 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 !16
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[I]], align 4
 | |
| ; CHECK-NEXT:    [[TMP10:%.*]] = icmp ne i32 [[TMP9]], 0
 | |
| ; CHECK-NEXT:    [[TMP11:%.*]] = and i32 [[TMP0]], 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 !15
 | |
| ; 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 !18
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP15:%.*]] = and i32 [[TMP0]], 8
 | |
| ; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP16]], i32 44, i32 88, !prof !16
 | |
| ; 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, i32* %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, i32* %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(i32* %i, i32* %j, i32 %sum0, i1 %pred, i32 %z) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_14(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[V1:%.*]] = icmp ne i32 [[Z:%.*]], 1
 | |
| ; CHECK-NEXT:    [[V0:%.*]] = icmp eq i32 [[Z]], 0
 | |
| ; CHECK-NEXT:    [[V3_NONCHR:%.*]] = and i1 [[V0]], [[PRED:%.*]]
 | |
| ; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[V1]], [[V3_NONCHR]]
 | |
| ; CHECK-NEXT:    br i1 [[OR_COND]], label [[BB0_NONCHR:%.*]], label [[BB1:%.*]], !prof !19
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB1]]
 | |
| ; CHECK:       bb1:
 | |
| ; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[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:%.*]] = and i1 [[V4]], [[V5]]
 | |
| ; CHECK-NEXT:    br i1 [[TMP0]], label [[BB1_SPLIT:%.*]], label [[BB1_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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 !16
 | |
| ; 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:    [[TMP1:%.*]] = phi i32 [ [[V8]], [[BB2]] ], [ [[V8]], [[BB1_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB2_NONCHR]] ], [ [[SUM3_NONCHR]], [[BB1_SPLIT_NONCHR]] ]
 | |
| ; CHECK-NEXT:    [[V11:%.*]] = add i32 [[I0]], [[TMP1]]
 | |
| ; CHECK-NEXT:    ret i32 [[V11]]
 | |
| ;
 | |
| entry:
 | |
|   %i0 = load i32, i32* %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, i32* %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(i32* %i, i32* %j, i32 %sum0, i1 %pred, i32 %z) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_15(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[V0:%.*]] = icmp eq i32 [[Z:%.*]], 0
 | |
| ; CHECK-NEXT:    [[V3:%.*]] = and i1 [[V0]], [[PRED:%.*]]
 | |
| ; CHECK-NEXT:    br i1 [[V3]], label [[BB0:%.*]], label [[BB1:%.*]], !prof !16
 | |
| ; CHECK:       bb0:
 | |
| ; CHECK-NEXT:    call void @foo()
 | |
| ; CHECK-NEXT:    br label [[BB1]]
 | |
| ; CHECK:       bb1:
 | |
| ; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
 | |
| ; 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 !16
 | |
| ; CHECK-NEXT:    [[V5:%.*]] = icmp eq i32 [[I0]], [[SUM2]]
 | |
| ; CHECK-NEXT:    [[SUM3:%.*]] = select i1 [[V5]], i32 [[SUM2]], i32 [[V8]], !prof !16
 | |
| ; 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:    [[V11:%.*]] = add i32 [[I0]], [[SUM3]]
 | |
| ; CHECK-NEXT:    ret i32 [[V11]]
 | |
| ;
 | |
| entry:
 | |
|   %i0 = load i32, i32* %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, i32* %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(i32* %i) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_16(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[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 !15
 | |
| ; 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:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; 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:    [[TMP5:%.*]] = and i32 [[TMP0]], 2
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
 | |
| ; 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:    [[TMP7:%.*]] = 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]], [[TMP7]]
 | |
| ; CHECK-NEXT:    ret i32 [[V43]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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 !16
 | |
| ; 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 !16
 | |
| ; 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(i32* %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, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[SUM1:%.*]] = add i32 [[SUM0:%.*]], 42
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[LI]], 5
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 5
 | |
| ; CHECK-NEXT:    br i1 [[TMP1]], label [[BB0_SPLIT:%.*]], label [[BB0_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; CHECK:       bb0.split:
 | |
| ; CHECK-NEXT:    [[INC2:%.*]] = add i32 [[INC1]], 1
 | |
| ; CHECK-NEXT:    [[SUM3:%.*]] = add i32 [[SUM0]], 86
 | |
| ; CHECK-NEXT:    br label [[BB2]]
 | |
| ; CHECK:       bb0.split.nonchr:
 | |
| ; CHECK-NEXT:    [[A4_NONCHR:%.*]] = and i32 [[LI]], 4
 | |
| ; CHECK-NEXT:    [[CMP4_NONCHR:%.*]] = icmp eq i32 [[A4_NONCHR]], 0
 | |
| ; CHECK-NEXT:    [[INC2_NONCHR:%.*]] = add i32 [[INC1]], 1
 | |
| ; CHECK-NEXT:    br i1 [[CMP4_NONCHR]], label [[BB2]], label [[BB1_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[A1:%.*]] = and i32 [[LI]], 1
 | |
| ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A1]], 0
 | |
| ; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[CMP1]], i32 [[SUM0]], i32 [[SUM1]], !prof !16
 | |
| ; CHECK-NEXT:    [[SUM3_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], 44
 | |
| ; CHECK-NEXT:    br label [[BB2]]
 | |
| ; CHECK:       bb2:
 | |
| ; CHECK-NEXT:    [[TMP2]] = phi i32 [ [[INC2]], [[BB0_SPLIT]] ], [ [[INC2_NONCHR]], [[BB1_NONCHR]] ], [ [[INC2_NONCHR]], [[BB0_SPLIT_NONCHR]] ]
 | |
| ; CHECK-NEXT:    [[SUM4:%.*]] = phi i32 [ [[SUM3]], [[BB0_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB1_NONCHR]] ], [ [[SUM1]], [[BB0_SPLIT_NONCHR]] ]
 | |
| ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP2]], 100
 | |
| ; CHECK-NEXT:    br i1 [[CMP]], label [[BB3:%.*]], label [[BB0]], !prof !16
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    ret i32 [[SUM4]]
 | |
| ;
 | |
| entry:
 | |
|   br label %bb0
 | |
| 
 | |
| bb0:
 | |
|   %inc1 = phi i32 [ %inc2, %bb2 ], [ 0, %entry ]
 | |
|   %li = load i32, i32* %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(i32* %i, i32 %sum0) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_19(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 9
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 9
 | |
| ; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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 [[TMP0]], 255
 | |
| ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 | |
| ; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb0.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 1
 | |
| ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
 | |
| ; CHECK-NEXT:    [[TMP9:%.*]] = add i32 [[SUM0]], 85
 | |
| ; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP8]], i32 [[SUM0]], i32 [[TMP9]], !prof !16
 | |
| ; CHECK-NEXT:    br i1 [[TMP8]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
 | |
| ; CHECK:       bb1.nonchr:
 | |
| ; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP0]], 8
 | |
| ; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP11]], i32 44, i32 88, !prof !16
 | |
| ; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
 | |
| ; CHECK-NEXT:    br label [[BB3]]
 | |
| ; CHECK:       bb3:
 | |
| ; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[TMP4]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
 | |
| ; CHECK-NEXT:    ret i32 [[SUM6]]
 | |
| ;
 | |
| entry:
 | |
|   %0 = load i32, i32* %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(i32* %i, i32 %sum0, i1 %j) !prof !14 {
 | |
| ; CHECK-LABEL: @test_chr_20(
 | |
| ; CHECK-NEXT:  entry:
 | |
| ; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
 | |
| ; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[I0]], 6
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 6
 | |
| ; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
 | |
| ; 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]], 2
 | |
| ; CHECK-NEXT:    [[V4:%.*]] = icmp eq i32 [[V3]], 0
 | |
| ; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof !16
 | |
| ; CHECK-NEXT:    [[V6_NONCHR:%.*]] = and i32 [[I0]], 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 !16
 | |
| ; 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, i32* [[I]], align 4
 | |
| ; CHECK-NEXT:    [[V12:%.*]] = icmp eq i32 [[I5]], 44
 | |
| ; CHECK-NEXT:    [[V13:%.*]] = select i1 [[V12]], i32 44, i32 [[TMP2]], !prof !16
 | |
| ; CHECK-NEXT:    ret i32 [[V13]]
 | |
| ;
 | |
| entry:
 | |
|   %i0 = load i32, i32* %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, i32* %i
 | |
|   %v12 = icmp eq i32 %i5, 44
 | |
|   %v13 = select i1 %v12, i32 %i5, i32 %sum3, !prof !15
 | |
|   ret i32 %v13
 | |
| }
 | |
| 
 | |
| !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}
 | |
| ; 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}
 | |
| ; CHECK: !19 = !{!"branch_weights", i32 0, i32 1000}
 |