forked from OSchip/llvm-project
240 lines
5.3 KiB
LLVM
240 lines
5.3 KiB
LLVM
; 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(i32* %p) {
|
|
entry:
|
|
br label %header
|
|
|
|
header:
|
|
%x1 = phi i64 [0, %entry], [%x2, %latch]
|
|
%count1 = phi i32 [0, %entry], [%count4, %latch]
|
|
%0 = ptrtoint i32* %p to i64
|
|
%1 = add i64 %0, %x1
|
|
%2 = inttoptr i64 %1 to i32*
|
|
%data = load i32, i32* %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(i32* %p) {
|
|
entry:
|
|
br label %header
|
|
|
|
header:
|
|
%x1 = phi i64 [0, %entry], [%x2, %latch]
|
|
%count1 = phi i32 [0, %entry], [%count4, %latch]
|
|
%0 = ptrtoint i32* %p to i64
|
|
%1 = add i64 %0, %x1
|
|
%2 = inttoptr i64 %1 to i32*
|
|
%data = load i32, i32* %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(i32* %p) {
|
|
entry:
|
|
br label %header
|
|
|
|
header:
|
|
%x1 = phi i64 [0, %entry], [%x2, %latch]
|
|
%count1 = phi i32 [0, %entry], [%count12, %latch]
|
|
%0 = ptrtoint i32* %p to i64
|
|
%1 = add i64 %0, %x1
|
|
%2 = inttoptr i64 %1 to i32*
|
|
%data = load i32, i32* %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, i32* %p) {
|
|
entry:
|
|
br label %header
|
|
|
|
header:
|
|
%x1 = phi i64 [0, %entry], [%x2, %latch]
|
|
%count1 = phi i32 [0, %entry], [%count4, %latch]
|
|
%0 = ptrtoint i32* %p to i64
|
|
%1 = add i64 %0, %x1
|
|
%2 = inttoptr i64 %1 to i32*
|
|
%data = load i32, i32* %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(i32* %p) {
|
|
entry:
|
|
br label %header
|
|
|
|
header:
|
|
%x1 = phi i64 [0, %entry], [%x1, %header], [%x2, %latch]
|
|
%0 = ptrtoint i32* %p to i64
|
|
%1 = add i64 %0, %x1
|
|
%2 = inttoptr i64 %1 to i32*
|
|
%data = load i32, i32* %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
|
|
}
|
|
|