1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00
llvm-mirror/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll
Florian Hahn f7c5e4104c [CallSiteSplitting] Support splitting of blocks with instrs before call.
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: 325001
2018-02-13 12:00:48 +00:00

254 lines
8.2 KiB
LLVM

; RUN: opt -S -callsite-splitting < %s | FileCheck --check-prefix=CHECK %s
; RUN: opt -S -callsite-splitting -callsite-splitting-duplication-threshold=0 < %s | FileCheck --check-prefix=NODUP %s
; Instructions before a call that will be pushed to its predecessors
; with uses after the callsite, must be patched up as PHI nodes in
; the join block.
define i32* @test_split_branch_phi(i32* %ptrarg, i32 %i) {
Header:
%tobool = icmp ne i32* %ptrarg, null
br i1 %tobool, label %TBB, label %CallSite
TBB: ; preds = %Header
%arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
%0 = load i32, i32* %arrayidx, align 4
%tobool1 = icmp ne i32 %0, 0
br i1 %tobool1, label %CallSite, label %End
CallSite: ; preds = %TBB, %Header
%somepointer = getelementptr i32, i32* %ptrarg, i64 18
call void @bar(i32* %ptrarg, i32 %i)
br label %End
End: ; preds = %CallSite, %TBB
%somepointerphi = phi i32* [ %somepointer, %CallSite ], [ null, %TBB ]
ret i32* %somepointerphi
}
; NODUP-LABEL: test_split_branch_phi
; NODUP-NOT: split
; CHECK-LABEL: Header.split
; CHECK: %[[V1:somepointer[0-9]+]] = getelementptr i32, i32* %ptrarg, i64 18
; CHECK: call void @bar(i32* null, i32 %i)
; CHECK: br label %CallSite
; CHECK-LABEL: TBB.split:
; CHECK: %[[V2:somepointer[0-9]+]] = getelementptr i32, i32* %ptrarg, i64 18
; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %i)
; CHECK: br label %CallSite
; CHECK: CallSite:
; CHECK: phi i32* [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ]
define void @split_branch_no_extra_phi(i32* %ptrarg, i32 %i) {
Header:
%tobool = icmp ne i32* %ptrarg, null
br i1 %tobool, label %TBB, label %CallSite
TBB: ; preds = %Header
%arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
%0 = load i32, i32* %arrayidx, align 4
%tobool1 = icmp ne i32 %0, 0
br i1 %tobool1, label %CallSite, label %End
CallSite: ; preds = %TBB, %Header
%i.add = add i32 %i, 99
call void @bar(i32* %ptrarg, i32 %i.add)
br label %End
End: ; preds = %CallSite, %TBB
ret void
}
; NODUP-LABEL: split_branch_no_extra_phi
; NODUP-NOT: split
; CHECK-LABEL: split_branch_no_extra_phi
; CHECK-LABEL: Header.split
; CHECK: %[[V1:.+]] = add i32 %i, 99
; CHECK: call void @bar(i32* null, i32 %[[V1]])
; CHECK: br label %CallSite
; CHECK-LABEL: TBB.split:
; CHECK: %[[V2:.+]] = add i32 %i, 99
; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %[[V2]])
; CHECK: br label %CallSite
; CHECK: CallSite:
; CHECK-NOT: phi
; In this test case, the codesize cost of the instructions before the call to
; bar() is equal to the default DuplicationThreshold of 5, because calls are
; more expensive.
define void @test_no_split_threshold(i32* %ptrarg, i32 %i) {
Header:
%tobool = icmp ne i32* %ptrarg, null
br i1 %tobool, label %TBB, label %CallSite
TBB: ; preds = %Header
%arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
%0 = load i32, i32* %arrayidx, align 4
%tobool1 = icmp ne i32 %0, 0
br i1 %tobool1, label %CallSite, label %End
CallSite: ; preds = %TBB, %Header
%i2 = add i32 %i, 10
call void @bari(i32 %i2)
call void @bari(i32 %i2)
call void @bar(i32* %ptrarg, i32 %i2)
br label %End
End: ; preds = %CallSite, %TBB
ret void
}
; NODUP-LABEL: test_no_split_threshold
; NODUP-NOT: split
; CHECK-LABEL: test_no_split_threshold
; CHECK-NOT: split
; CHECK-LABEL: CallSite:
; CHECK: call void @bar(i32* %ptrarg, i32 %i2)
; In this test case, the phi node %l in CallSite should be removed, as after
; moving the call to the split blocks we can use the values directly.
define void @test_remove_unused_phi(i32* %ptrarg, i32 %i) {
Header:
%l1 = load i32, i32* undef, align 16
%tobool = icmp ne i32* %ptrarg, null
br i1 %tobool, label %TBB, label %CallSite
TBB: ; preds = %Header
%arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
%0 = load i32, i32* %arrayidx, align 4
%l2 = load i32, i32* undef, align 16
%tobool1 = icmp ne i32 %0, 0
br i1 %tobool1, label %CallSite, label %End
CallSite: ; preds = %TBB, %Header
%l = phi i32 [ %l1, %Header ], [ %l2, %TBB ]
call void @bar(i32* %ptrarg, i32 %l)
br label %End
End: ; preds = %CallSite, %TBB
ret void
}
; NODUP-LABEL: test_remove_unused_phi
; NODUP-NOT: split
; CHECK-LABEL: test_remove_unused_phi
; CHECK-LABEL: Header.split
; CHECK: call void @bar(i32* null, i32 %l1)
; CHECK: br label %CallSite
; CHECK-LABEL: TBB.split:
; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %l2)
; CHECK: br label %CallSite
; CHECK-LABEL: CallSite:
; CHECK-NOT: phi
; In this test case, we need to insert a new PHI node in TailBB to combine
; the loads we moved to the predecessors.
define void @test_add_new_phi(i32* %ptrarg, i32 %i) {
Header:
%tobool = icmp ne i32* %ptrarg, null
br i1 %tobool, label %TBB, label %CallSite
TBB:
br i1 undef, label %CallSite, label %End
CallSite:
%arrayidx112 = getelementptr inbounds i32, i32* undef, i64 1
%0 = load i32, i32* %arrayidx112, align 4
call void @bar(i32* %ptrarg, i32 %i)
%sub = sub nsw i32 %0, undef
br label %End
End: ; preds = %CallSite, %TBB
ret void
}
; NODUP-LABEL: test_add_new_phi
; NODUP-NOT: split
; CHECK-LABEL: test_add_new_phi
; CHECK-LABEL: Header.split
; CHECK: %[[V1:.+]] = load i32, i32*
; CHECK: call void @bar(i32* null, i32 %i)
; CHECK: br label %CallSite
; CHECK-LABEL: TBB.split:
; CHECK: %[[V2:.+]] = load i32, i32*
; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %i)
; CHECK: br label %CallSite
; CHECK-LABEL: CallSite:
; CHECK-NEXT: %[[V3:.+]] = phi i32 [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ]
; CHECK: %sub = sub nsw i32 %[[V3]], undef
define i32 @test_firstnophi(i32* %a, i32 %v) {
Header:
%tobool1 = icmp eq i32* %a, null
br i1 %tobool1, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, 1
br i1 %cmp, label %Tail, label %End
Tail:
%p = phi i32[1,%Header], [2, %TBB]
store i32 %v, i32* %a
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
; NODUP-LABEL: @test_firstnophi
; NODUP-NOT: split:
; CHECK-LABEL: @test_firstnophi
; CHECK-LABEL: Header.split:
; CHECK-NEXT: store i32 %v, i32* %a
; CHECK-NEXT: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
; CHECK-NEXT: br label %Tail
; CHECK-LABEL: TBB.split:
; CHECK-NEXT: store i32 %v, i32* %a
; CHECK-NEXT: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
; CHECK-NEXT br label %Tail
; CHECK-LABEL: Tail:
; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
; CHECK: ret i32 %[[MERGED]]
define i32 @callee(i32* %a, i32 %v, i32 %p) {
ret i32 0
}
define void @test_no_remove_used_phi(i32* %ptrarg, i32 %i) {
Header:
%l1 = load i32, i32* undef, align 16
%tobool = icmp ne i32* %ptrarg, null
br i1 %tobool, label %TBB, label %CallSite
TBB: ; preds = %Header
%arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
%0 = load i32, i32* %arrayidx, align 4
%l2 = load i32, i32* undef, align 16
%tobool1 = icmp ne i32 %0, 0
br i1 %tobool1, label %CallSite, label %End
CallSite: ; preds = %TBB, %Header
%l = phi i32 [ %l1, %Header ], [ %l2, %TBB ]
call void @bar(i32* %ptrarg, i32 %l)
call void @bari(i32 %l)
br label %End
End: ; preds = %CallSite, %TBB
ret void
}
; NODUP-LABEL: @test_no_remove_used_phi
; NODUP-NOT: split
; CHECK-LABEL: @test_no_remove_used_phi
; CHECK-LABEL: Header.split:
; CHECK: call void @bar(i32* null, i32 %l1)
; CHECK-NEXT: br label %CallSite
; CHECK-LABEL: TBB.split:
; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %l2)
; CHECK-NEXT br label %CallSite
; CHECK-LABEL: CallSite:
; CHECK-NEXT: %l = phi i32 [ %l1, %Header.split ], [ %l2, %TBB.split ]
; CHECK: call void @bari(i32 %l)
define void @bar(i32*, i32) {
ret void
}
define void @bari(i32) {
ret void
}