Files
clang-p2996/llvm/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll
Florian Hahn beda7d517d [CallSiteSplitting] Refactor creating callsites.
Summary:
This change makes the call site creation more general if any of the
arguments is predicated on a condition in the call site's predecessors.

If we find a callsite, that potentially can be split, we collect the set
of conditions for the call site's predecessors (currently only 2
predecessors are allowed). To do that, we traverse each predecessor's
predecessors as long as it only has single predecessors and record the
condition, if it is relevant to the call site. For each condition, we
also check if the condition is taken or not. In case it is not taken,
we record the inverse predicate.

We use the recorded conditions to create the new call sites and split
the basic block.

This has 2 benefits: (1) it is slightly easier to see what is going on
(IMO) and (2) we can easily extend it to handle more complex control
flow.

Reviewers: davidxl, junbuml

Reviewed By: junbuml

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D40728

llvm-svn: 320547
2017-12-13 03:05:20 +00:00

564 lines
15 KiB
LLVM

; RUN: opt < %s -callsite-splitting -S | FileCheck %s
; RUN: opt < %s -passes='function(callsite-splitting)' -S | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-linaro-linux-gnueabi"
;CHECK-LABEL: @test_eq_eq
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq(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]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_eq_eq_eq
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 10)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_eq(i32* %a, i32 %v, i32 %p) {
Header:
%tobool1 = icmp eq i32* %a, null
br i1 %tobool1, label %Header2, label %End
Header2:
%tobool2 = icmp eq i32 %p, 10
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, 1
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_constrain_same_i32_arg
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 222, i32 %p)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 333, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_eq_constrain_same_i32_arg(i32* %a, i32 %v, i32 %p) {
Header:
%tobool1 = icmp eq i32 %v, 111
br i1 %tobool1, label %Header2, label %End
Header2:
%tobool2 = icmp eq i32 %v, 222
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, 333
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_ne_eq
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq(i32* %a, i32 %v) {
Header:
%tobool1 = icmp ne 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]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_ne_eq_ne
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 10)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq_ne(i32* %a, i32 %v, i32 %p) {
Header:
%tobool1 = icmp ne i32* %a, null
br i1 %tobool1, label %Header2, label %End
Header2:
%tobool2 = icmp eq i32 %p, 10
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp ne i32 %v, 1
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_ne_ne
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_ne(i32* %a, i32 %v) {
Header:
%tobool1 = icmp ne i32* %a, null
br i1 %tobool1, label %Tail, label %TBB
TBB:
%cmp = icmp ne i32 %v, 1
br i1 %cmp, label %Tail, label %End
Tail:
%p = phi i32[1,%Header], [2, %TBB]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_ne_ne_ne_constrain_same_pointer_arg
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_ne_ne_constrain_same_pointer_arg(i32* %a, i32 %v, i32 %p, i32* %a2, i32* %a3) {
Header:
%tobool1 = icmp ne i32* %a, null
br i1 %tobool1, label %Header2, label %End
Header2:
%tobool2 = icmp ne i32* %a, %a2
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp ne i32* %a, %a3
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_untaken
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_untaken(i32* %a, i32 %v) {
Header:
%tobool1 = icmp eq i32* %a, null
br i1 %tobool1, label %TBB, label %Tail
TBB:
%cmp = icmp eq i32 %v, 1
br i1 %cmp, label %Tail, label %End
Tail:
%p = phi i32[1,%Header], [2, %TBB]
%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: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 10)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_eq_untaken(i32* %a, i32 %v, i32 %p) {
Header:
%tobool1 = icmp eq i32* %a, null
br i1 %tobool1, label %End, label %Header2
Header2:
%tobool2 = icmp eq i32 %p, 10
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, 1
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_ne_eq_untaken
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq_untaken(i32* %a, i32 %v) {
Header:
%tobool1 = icmp ne i32* %a, null
br i1 %tobool1, label %TBB, label %Tail
TBB:
%cmp = icmp eq i32 %v, 1
br i1 %cmp, label %Tail, label %End
Tail:
%p = phi i32[1,%Header], [2, %TBB]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_ne_eq_ne_untaken
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 10)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq_ne_untaken(i32* %a, i32 %v, i32 %p) {
Header:
%tobool1 = icmp ne i32* %a, null
br i1 %tobool1, label %End, label %Header2
Header2:
%tobool2 = icmp eq i32 %p, 10
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp ne i32 %v, 1
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_ne_ne_untaken
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_ne_untaken(i32* %a, i32 %v) {
Header:
%tobool1 = icmp ne i32* %a, null
br i1 %tobool1, label %TBB, label %Tail
TBB:
%cmp = icmp ne i32 %v, 1
br i1 %cmp, label %End, label %Tail
Tail:
%p = phi i32[1,%Header], [2, %TBB]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_nonconst_const_phi
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 1, %Tail.predBB1.split ], [ 2, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_nonconst_const_phi(i32* %a, i32* %b, i32 %v) {
Header:
%tobool1 = icmp eq i32* %a, %b
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]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_nonconst_nonconst_phi
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 2)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 2, %Tail.predBB1.split ], [ 1, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_nonconst_nonconst_phi(i32* %a, i32* %b, i32 %v, i32 %v2) {
Header:
%tobool1 = icmp eq i32* %a, %b
br i1 %tobool1, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, %v2
br i1 %cmp, label %Tail, label %End
Tail:
%p = phi i32[1,%Header], [2, %TBB]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_cfg_no_or_phi
;CHECK-LABEL: Tail.predBB1.split
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 2)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
;CHECK-LABEL: Tail
;CHECK: %p = phi i32 [ 2, %Tail.predBB1.split ], [ 1, %Tail.predBB2.split ]
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_cfg_no_or_phi(i32* %a, i32 %v) {
entry:
br i1 undef, label %TBB0, label %TBB1
TBB0:
br i1 undef, label %Tail, label %End
TBB1:
br i1 undef, label %Tail, label %End
Tail:
%p = phi i32[1,%TBB0], [2, %TBB1]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_nonconst_nonconst_phi_noncost
;CHECK-NOT: Tail.predBB1.split:
;CHECK-NOT: Tail.predBB2.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_nonconst_nonconst_phi_noncost(i32* %a, i32* %b, i32 %v, i32 %v2) {
Header:
%tobool1 = icmp eq i32* %a, %b
br i1 %tobool1, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, %v2
br i1 %cmp, label %Tail, label %End
Tail:
%p = phi i32[%v,%Header], [%v2, %TBB]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_fisrtnonphi
;CHECK-NOT: Tail.predBB1.split:
;CHECK-NOT: Tail.predBB2.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_fisrtnonphi(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
}
;CHECK-LABEL: @test_3preds_constphi
;CHECK-NOT: Tail.predBB1.split:
;CHECK-NOT: Tail.predBB2.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_3preds_constphi(i32* %a, i32 %v, i1 %c1, i1 %c2, i1 %c3) {
Header:
br i1 %c1, label %Tail, label %TBB1
TBB1:
br i1 %c2, label %Tail, label %TBB2
TBB2:
br i1 %c3, label %Tail, label %End
Tail:
%p = phi i32[1,%Header], [2, %TBB1], [3, %TBB2]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_indirectbr_phi
;CHECK-NOT: Tail.predBB1.split:
;CHECK-NOT: Tail.predBB2.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_indirectbr_phi(i8* %address, i32* %a, i32* %b, i32 %v) {
Header:
%indirect.goto.dest = select i1 undef, i8* blockaddress(@test_indirectbr_phi, %End), i8* %address
indirectbr i8* %indirect.goto.dest, [label %TBB, label %Tail]
TBB:
%indirect.goto.dest2 = select i1 undef, i8* blockaddress(@test_indirectbr_phi, %End), i8* %address
indirectbr i8* %indirect.goto.dest2, [label %Tail, label %End]
Tail:
%p = phi i32[1,%Header], [2, %TBB]
%r = call i32 @callee(i32* %a, i32 %v, i32 %p)
ret i32 %r
End:
ret i32 %v
}
;CHECK-LABEL: @test_unreachable
;CHECK-LABEL: Tail.predBB1.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 10)
;CHECK-LABEL: Tail.predBB2.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 1, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB1.split ], [ %[[CALL2]], %Tail.predBB2.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_unreachable(i32* %a, i32 %v, i32 %p) {
Entry:
br label %End
Header:
%tobool2 = icmp eq i32 %p, 10
br i1 %tobool2, label %Tail, label %TBB
TBB:
%cmp = icmp eq i32 %v, 1
br i1 %cmp, label %Tail, label %Header
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) {
entry:
%c = icmp ne i32* %a, null
br i1 %c, label %BB1, label %BB2
BB1:
call void @dummy(i32* %a, i32 %p)
br label %End
BB2:
call void @dummy2(i32 %v, i32 %p)
br label %End
End:
ret i32 %p
}
declare void @dummy(i32*, i32)
declare void @dummy2(i32, i32)