; RUN: llc -mcpu=corei7 -mtriple=x86_64-linux < %s | FileCheck %s
; The block latch should be moved before header.
;CHECK-LABEL: test1:
;CHECK: %latch
;CHECK: %header
;CHECK: %false
define i32 @test1(ptr %p) {
entry:
br label %header
header:
%x1 = phi i64 [0, %entry], [%x2, %latch]
%count1 = phi i32 [0, %entry], [%count4, %latch]
%0 = ptrtoint ptr %p to i64
%1 = add i64 %0, %x1
%2 = inttoptr i64 %1 to ptr
%data = load i32, ptr %2
%3 = icmp eq i32 %data, 0
br i1 %3, label %latch, label %false
false:
%count2 = add i32 %count1, 1
br label %latch
latch:
%count4 = phi i32 [%count2, %false], [%count1, %header]
%x2 = add i64 %x1, 1
%4 = icmp eq i64 %x2, 100
br i1 %4, label %exit, label %header
exit:
ret i32 %count4
}
; The block latch and one of false/true should be moved before header.
;CHECK-LABEL: test2:
;CHECK: %true
;CHECK: %latch
;CHECK: %header
;CHECK: %false
define i32 @test2(ptr %p) {
entry:
br label %header
header:
%x1 = phi i64 [0, %entry], [%x2, %latch]
%count1 = phi i32 [0, %entry], [%count4, %latch]
%0 = ptrtoint ptr %p to i64
%1 = add i64 %0, %x1
%2 = inttoptr i64 %1 to ptr
%data = load i32, ptr %2
%3 = icmp eq i32 %data, 0
br i1 %3, label %true, label %false
false:
%count2 = add i32 %count1, 1
br label %latch
true:
%count3 = add i32 %count1, 2
br label %latch
latch:
%count4 = phi i32 [%count2, %false], [%count3, %true]
%x2 = add i64 %x1, 1
%4 = icmp eq i64 %x2, 100
br i1 %4, label %exit, label %header
exit:
ret i32 %count4
}
; More blocks can be moved before header.
; header <------------
; /\ |
; / \ |
; / \ |
; / \ |
; / \ |
; true false |
; /\ /\ |
; / \ / \ |
; / \ / \ |
; true3 false3 / \ |
; \ / true2 false2 |
; \ / \ / |
; \/ \ / |
; endif3 \ / |
; \ \/ |
; \ endif2 |
; \ / |
; \ / |
; \ / |
; \ / |
; \/ |
; latch-------------
; |
; |
; exit
;
; Blocks true3,endif3,latch should be moved before header.
;
;CHECK-LABEL: test3:
;CHECK: %true3
;CHECK: %endif3
;CHECK: %latch
;CHECK: %header
;CHECK: %false
define i32 @test3(ptr %p) {
entry:
br label %header
header:
%x1 = phi i64 [0, %entry], [%x2, %latch]
%count1 = phi i32 [0, %entry], [%count12, %latch]
%0 = ptrtoint ptr %p to i64
%1 = add i64 %0, %x1
%2 = inttoptr i64 %1 to ptr
%data = load i32, ptr %2
%3 = icmp eq i32 %data, 0
br i1 %3, label %true, label %false, !prof !3
false:
%count2 = add i32 %count1, 1
%cond = icmp sgt i32 %count2, 10
br i1 %cond, label %true2, label %false2
false2:
%count3 = and i32 %count2, 7
br label %endif2
true2:
%count4 = mul i32 %count2, 3
br label %endif2
endif2:
%count5 = phi i32 [%count3, %false2], [%count4, %true2]
%count6 = sub i32 %count5, 5
br label %latch
true:
%count7 = add i32 %count1, 2
%cond2 = icmp slt i32 %count7, 20
br i1 %cond2, label %true3, label %false3
false3:
%count8 = or i32 %count7, 3
br label %endif3
true3:
%count9 = xor i32 %count7, 55
br label %endif3
endif3:
%count10 = phi i32 [%count8, %false3], [%count9, %true3]
%count11 = add i32 %count10, 3
br label %latch
latch:
%count12 = phi i32 [%count6, %endif2], [%count11, %endif3]
%x2 = add i64 %x1, 1
%4 = icmp eq i64 %x2, 100
br i1 %4, label %exit, label %header
exit:
ret i32 %count12
}
; The exit block has higher frequency than false block, so latch block
; should not moved before header.
;CHECK-LABEL: test4:
;CHECK: %header
;CHECK: %true
;CHECK: %latch
;CHECK: %false
;CHECK: %exit
define i32 @test4(i32 %t, ptr %p) {
entry:
br label %header
header:
%x1 = phi i64 [0, %entry], [%x2, %latch]
%count1 = phi i32 [0, %entry], [%count4, %latch]
%0 = ptrtoint ptr %p to i64
%1 = add i64 %0, %x1
%2 = inttoptr i64 %1 to ptr
%data = load i32, ptr %2
%3 = icmp eq i32 %data, 0
br i1 %3, label %true, label %false, !prof !1
false:
%count2 = add i32 %count1, 1
br label %latch
true:
%count3 = add i32 %count1, 2
br label %latch
latch:
%count4 = phi i32 [%count2, %false], [%count3, %true]
%x2 = add i64 %x1, 1
%4 = icmp eq i64 %x2, 100
br i1 %4, label %exit, label %header, !prof !2
exit:
ret i32 %count4
}
!1 = !{!"branch_weights", i32 100, i32 1}
!2 = !{!"branch_weights", i32 16, i32 16}
!3 = !{!"branch_weights", i32 51, i32 49}
; If move latch to loop top doesn't reduce taken branch, don't do it.
;CHECK-LABEL: test5:
;CHECK: %entry
;CHECK: %header
;CHECK: %latch
define void @test5(ptr %p) {
entry:
br label %header
header:
%x1 = phi i64 [0, %entry], [%x1, %header], [%x2, %latch]
%0 = ptrtoint ptr %p to i64
%1 = add i64 %0, %x1
%2 = inttoptr i64 %1 to ptr
%data = load i32, ptr %2
%3 = icmp eq i32 %data, 0
br i1 %3, label %latch, label %header
latch:
%x2 = add i64 %x1, 1
br label %header
exit:
ret void
}