mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
96b6dea648
Summary: Blocks ending in unreachable are typically cold because they end the program or throw an exception, so merging them with other identical blocks is usually profitable because it reduces the size of cold code. MachineBlockPlacement generally does not arrange to fall through to such blocks, so commoning these blocks will not introduce additional unconditional branches. Reviewers: hans, iteratee, haicheng Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D29153 llvm-svn: 295105
120 lines
2.5 KiB
LLVM
120 lines
2.5 KiB
LLVM
; RUN: llc < %s -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic -mcpu=cortex-a8 -asm-verbose=false | FileCheck %s
|
|
|
|
declare void @bar(i32)
|
|
declare void @car(i32)
|
|
declare void @dar(i32)
|
|
declare void @ear(i32)
|
|
declare void @far(i32)
|
|
declare i1 @qux()
|
|
|
|
@GHJK = global i32 0
|
|
|
|
declare i8* @choose(i8*, i8*)
|
|
|
|
; BranchFolding should tail-duplicate the indirect jump to avoid
|
|
; redundant branching.
|
|
|
|
; CHECK-LABEL: tail_duplicate_me:
|
|
; CHECK: qux
|
|
; CHECK: movw r{{[0-9]+}}, :lower16:_GHJK
|
|
; CHECK: movt r{{[0-9]+}}, :upper16:_GHJK
|
|
; CHECK: str r
|
|
; CHECK-NEXT: bx r
|
|
; CHECK: qux
|
|
; CHECK: movw r{{[0-9]+}}, :lower16:_GHJK
|
|
; CHECK: movt r{{[0-9]+}}, :upper16:_GHJK
|
|
; CHECK: str r
|
|
; CHECK-NEXT: bx r
|
|
; CHECK: movw r{{[0-9]+}}, :lower16:_GHJK
|
|
; CHECK: movt r{{[0-9]+}}, :upper16:_GHJK
|
|
; CHECK: str r
|
|
; CHECK-NEXT: bx r
|
|
|
|
define void @tail_duplicate_me() nounwind {
|
|
entry:
|
|
%a = call i1 @qux()
|
|
%c = call i8* @choose(i8* blockaddress(@tail_duplicate_me, %return),
|
|
i8* blockaddress(@tail_duplicate_me, %altret))
|
|
br i1 %a, label %A, label %next
|
|
next:
|
|
%b = call i1 @qux()
|
|
br i1 %b, label %B, label %C
|
|
|
|
A:
|
|
call void @bar(i32 0)
|
|
store i32 0, i32* @GHJK
|
|
br label %M
|
|
|
|
B:
|
|
call void @car(i32 1)
|
|
store i32 0, i32* @GHJK
|
|
br label %M
|
|
|
|
C:
|
|
call void @dar(i32 2)
|
|
store i32 0, i32* @GHJK
|
|
br label %M
|
|
|
|
M:
|
|
indirectbr i8* %c, [label %return, label %altret]
|
|
|
|
return:
|
|
call void @ear(i32 1000)
|
|
ret void
|
|
altret:
|
|
call void @far(i32 1001)
|
|
ret void
|
|
}
|
|
|
|
; Use alternating abort functions so that the blocks we wish to merge are not
|
|
; layout successors during branch folding.
|
|
|
|
; CHECK-LABEL: merge_alternating_aborts:
|
|
; CHECK-NOT: _abort
|
|
; CHECK-NOT: _alt_abort
|
|
; CHECK: bxne lr
|
|
; CHECK-NOT: _abort
|
|
; CHECK-NOT: _alt_abort
|
|
; CHECK: LBB{{.*}}:
|
|
; CHECK: mov lr, pc
|
|
; CHECK: b _alt_abort
|
|
; CHECK-NOT: _abort
|
|
; CHECK-NOT: _alt_abort
|
|
; CHECK: LBB{{.*}}:
|
|
; CHECK: mov lr, pc
|
|
; CHECK: b _abort
|
|
; CHECK-NOT: _abort
|
|
; CHECK-NOT: _alt_abort
|
|
|
|
declare void @abort()
|
|
declare void @alt_abort()
|
|
|
|
define void @merge_alternating_aborts() {
|
|
entry:
|
|
%c1 = call i1 @qux()
|
|
br i1 %c1, label %cont1, label %abort1
|
|
abort1:
|
|
call void @abort()
|
|
unreachable
|
|
cont1:
|
|
%c2 = call i1 @qux()
|
|
br i1 %c2, label %cont2, label %abort2
|
|
abort2:
|
|
call void @alt_abort()
|
|
unreachable
|
|
cont2:
|
|
%c3 = call i1 @qux()
|
|
br i1 %c3, label %cont3, label %abort3
|
|
abort3:
|
|
call void @abort()
|
|
unreachable
|
|
cont3:
|
|
%c4 = call i1 @qux()
|
|
br i1 %c4, label %cont4, label %abort4
|
|
abort4:
|
|
call void @alt_abort()
|
|
unreachable
|
|
cont4:
|
|
ret void
|
|
}
|