mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
6252c9b891
For basic blocks with instructions between the beginning of the block and a call we have to duplicate the instructions before the call in all split blocks and add PHI nodes for uses of the duplicated instructions after the call. Currently, the threshold for the number of instructions before a call is quite low, to keep the impact on binary size low. Reviewers: junbuml, mcrosier, davidxl, davide Reviewed By: junbuml Differential Revision: https://reviews.llvm.org/D41860 llvm-svn: 325126
140 lines
3.9 KiB
LLVM
140 lines
3.9 KiB
LLVM
; RUN: opt < %s -callsite-splitting -S | FileCheck %s
|
|
; RUN: opt < %s -passes='function(callsite-splitting)' -S | FileCheck %s
|
|
|
|
; CHECK-LABEL: @test_simple
|
|
; CHECK-LABEL: Header:
|
|
; CHECK-NEXT: br i1 undef, label %Header.split
|
|
; CHECK-LABEL: Header.split:
|
|
; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 %p)
|
|
; CHECK-LABEL: TBB:
|
|
; CHECK: br i1 %cmp, label %TBB.split
|
|
; CHECK-LABEL: TBB.split:
|
|
; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 %p)
|
|
; CHECK-LABEL: Tail
|
|
; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
|
|
; CHECK: ret i32 %[[MERGED]]
|
|
define i32 @test_simple(i32* %a, i32 %v, i32 %p) {
|
|
Header:
|
|
br i1 undef, label %Tail, label %End
|
|
|
|
TBB:
|
|
%cmp = icmp eq i32* %a, null
|
|
br i1 %cmp, label %Tail, label %End
|
|
|
|
Tail:
|
|
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
|
|
ret i32 %r
|
|
|
|
End:
|
|
ret i32 %v
|
|
}
|
|
|
|
; CHECK-LABEL: @test_eq_eq_eq_untaken
|
|
; CHECK-LABEL: Header:
|
|
; CHECK: br i1 %tobool1, label %TBB1, label %Header.split
|
|
; CHECK-LABEL: Header.split:
|
|
; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
|
|
; CHECK-LABEL: TBB2:
|
|
; CHECK: br i1 %cmp2, label %TBB2.split, label %End
|
|
; CHECK-LABEL: TBB2.split:
|
|
; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 99)
|
|
; CHECK-LABEL: Tail
|
|
; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB2.split ]
|
|
; CHECK: ret i32 %[[MERGED]]
|
|
define i32 @test_eq_eq_eq_untaken2(i32* %a, i32 %v, i32 %p) {
|
|
Header:
|
|
%tobool1 = icmp eq i32* %a, null
|
|
br i1 %tobool1, label %TBB1, label %Tail
|
|
|
|
TBB1:
|
|
%cmp1 = icmp eq i32 %v, 1
|
|
br i1 %cmp1, label %TBB2, label %End
|
|
|
|
TBB2:
|
|
%cmp2 = icmp eq i32 %p, 99
|
|
br i1 %cmp2, label %Tail, label %End
|
|
|
|
Tail:
|
|
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
|
|
ret i32 %r
|
|
|
|
End:
|
|
ret i32 %v
|
|
}
|
|
|
|
; CHECK-LABEL: @test_eq_ne_eq_untaken
|
|
; CHECK-LABEL: Header:
|
|
; CHECK: br i1 %tobool1, label %TBB1, label %Header.split
|
|
; CHECK-LABEL: Header.split:
|
|
; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
|
|
; CHECK-LABEL: TBB2:
|
|
; CHECK: br i1 %cmp2, label %TBB2.split, label %End
|
|
; CHECK-LABEL: TBB2.split:
|
|
; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 99)
|
|
; CHECK-LABEL: Tail
|
|
; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB2.split ]
|
|
; CHECK: ret i32 %[[MERGED]]
|
|
define i32 @test_eq_ne_eq_untaken(i32* %a, i32 %v, i32 %p) {
|
|
Header:
|
|
%tobool1 = icmp eq i32* %a, null
|
|
br i1 %tobool1, label %TBB1, label %Tail
|
|
|
|
TBB1:
|
|
%cmp1 = icmp ne i32 %v, 1
|
|
br i1 %cmp1, label %TBB2, label %End
|
|
|
|
TBB2:
|
|
%cmp2 = icmp eq i32 %p, 99
|
|
br i1 %cmp2, label %Tail, label %End
|
|
|
|
Tail:
|
|
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
|
|
ret i32 %r
|
|
|
|
End:
|
|
ret i32 %v
|
|
}
|
|
|
|
; CHECK-LABEL: @test_header_header2_tbb
|
|
; CHECK: Header2:
|
|
; CHECK:br i1 %tobool2, label %Header2.split, label %TBB1
|
|
; CHECK-LABEL: Header2.split:
|
|
; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 10)
|
|
; CHECK-LABEL: TBB2:
|
|
; CHECK: br i1 %cmp2, label %TBB2.split, label %End
|
|
; CHECK-LABEL: TBB2.split:
|
|
; NOTE: CallSiteSplitting cannot infer that %a is null here, as it currently
|
|
; only supports recording conditions along a single predecessor path.
|
|
; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 1, i32 99)
|
|
; CHECK-LABEL: Tail
|
|
; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB2.split ]
|
|
; CHECK: ret i32 %[[MERGED]]
|
|
define i32 @test_header_header2_tbb(i32* %a, i32 %v, i32 %p) {
|
|
Header:
|
|
%tobool1 = icmp eq i32* %a, null
|
|
br i1 %tobool1, label %TBB1, label %Header2
|
|
|
|
Header2:
|
|
%tobool2 = icmp eq i32 %p, 10
|
|
br i1 %tobool2, label %Tail, label %TBB1
|
|
|
|
TBB1:
|
|
%cmp1 = icmp eq i32 %v, 1
|
|
br i1 %cmp1, label %TBB2, label %End
|
|
|
|
TBB2:
|
|
%cmp2 = icmp eq i32 %p, 99
|
|
br i1 %cmp2, label %Tail, label %End
|
|
|
|
Tail:
|
|
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
|
|
ret i32 %r
|
|
|
|
End:
|
|
ret i32 %v
|
|
}
|
|
|
|
define i32 @callee(i32* %a, i32 %v, i32 %p) {
|
|
ret i32 10
|
|
}
|