llvm/llvm/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll

; RUN: opt < %s -passes=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"

;CHECK-LABEL: @test_eq_eq

;CHECK-LABEL: Header:
;CHECK: br i1 %tobool1, label %Header.split, label %TBB
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr null, i32 %v, i32 1)
;CHECK-LABEL: TBB:
;CHECK: br i1 %cmp, label %TBB.split, label %End
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr nonnull %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq(ptr %a, i32 %v) {
Header:
  %tobool1 = icmp eq ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_eq_eq_eq
;CHECK-LABEL: Header2.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr %a, i32 %v, i32 10)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 1, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_eq(ptr %a, i32 %v, i32 %p) {
Header:
  %tobool1 = icmp eq ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_eq_eq_eq_constrain_same_i32_arg
;CHECK-LABEL: Header2.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr %a, i32 222, i32 %p)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 333, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_eq_constrain_same_i32_arg(ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_eq
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr nonnull %a, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr null, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq(ptr %a, i32 %v) {
Header:
  %tobool1 = icmp ne ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_eq_ne
;CHECK-LABEL: Header2.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr nonnull %a, i32 %v, i32 10)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 %v, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq_ne(ptr %a, i32 %v, i32 %p) {
Header:
  %tobool1 = icmp ne ptr %a, null
  br i1 %tobool1, label %Header2, label %TBB

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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_ne
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr nonnull %a, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr null, i32 %v, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_ne(ptr %a, i32 %v) {
Header:
  %tobool1 = icmp ne ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_ne_ne_constrain_same_pointer_arg
;CHECK-LABEL: Header2.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr nonnull %a, i32 %v, i32 %p)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 %v, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_ne_ne_constrain_same_pointer_arg(ptr %a, i32 %v, i32 %p, ptr %a2, ptr %a3) {
Header:
  %tobool1 = icmp ne ptr %a, null
  br i1 %tobool1, label %Header2, label %TBB

Header2:
  %tobool2 = icmp ne ptr %a, %a2
  br i1 %tobool2, label %Tail, label %TBB

TBB:
  %cmp = icmp ne ptr %a, %a3
  br i1 %cmp, label %Tail, label %End

Tail:
  %r = call i32 @callee(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}



;CHECK-LABEL: @test_eq_eq_untaken
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr nonnull %a, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr null, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_untaken(ptr %a, i32 %v) {
Header:
  %tobool1 = icmp eq ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_eq_eq_eq_untaken
;CHECK-LABEL: Header2.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr nonnull %a, i32 %v, i32 10)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 1, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_eq_eq_eq_untaken(ptr %a, i32 %v, i32 %p) {
Header:
  %tobool1 = icmp eq ptr %a, null
  br i1 %tobool1, label %TBB, 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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_eq_untaken
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr null, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr nonnull %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq_untaken(ptr %a, i32 %v) {
Header:
  %tobool1 = icmp ne ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_eq_ne_untaken
;CHECK-LABEL: Header2.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr null, i32 %v, i32 10)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 %v, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_eq_ne_untaken(ptr %a, i32 %v, i32 %p) {
Header:
  %tobool1 = icmp ne ptr %a, null
  br i1 %tobool1, label %TBB, 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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_ne_ne_untaken
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr null, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr nonnull %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_ne_ne_untaken(ptr %a, i32 %v) {
Header:
  %tobool1 = icmp ne ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_nonconst_const_phi
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr %a, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 1, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_nonconst_const_phi(ptr %a, ptr %b, i32 %v) {
Header:
  %tobool1 = icmp eq ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_nonconst_nonconst_phi
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr %a, i32 %v, i32 1)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 %v, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL2]], %TBB.split ], [ %[[CALL1]], %Header.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_nonconst_nonconst_phi(ptr %a, ptr %b, i32 %v, i32 %v2) {
Header:
  %tobool1 = icmp eq ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_cfg_no_or_phi
;CHECK-LABEL: TBB0.split
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr %a, i32 %v, i32 1)
;CHECK-LABEL: TBB1.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 %v, i32 2)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL2]], %TBB1.split ], [ %[[CALL1]], %TBB0.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_cfg_no_or_phi(ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r
End:
  ret i32 %v
}

;CHECK-LABEL: @test_nonconst_nonconst_phi_noncost
;CHECK-NOT: Header.split:
;CHECK-NOT: TBB.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(ptr %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_nonconst_nonconst_phi_noncost(ptr %a, ptr %b, i32 %v, i32 %v2) {
Header:
  %tobool1 = icmp eq ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_3preds_constphi
;CHECK-NOT: Header.split:
;CHECK-NOT: TBB.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(ptr %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_3preds_constphi(ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_indirectbr_phi
;CHECK-NOT: Header.split:
;CHECK-NOT: TBB.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(ptr %a, i32 %v, i32 %p)
;CHECK: ret i32 %r
define i32 @test_indirectbr_phi(ptr %address, ptr %a, ptr %b, i32 %v) {
Header:
   %indirect.goto.dest = select i1 undef, ptr blockaddress(@test_indirectbr_phi, %End), ptr %address
   indirectbr ptr %indirect.goto.dest, [label %TBB, label %Tail]

TBB:
  %indirect.goto.dest2 = select i1 undef, ptr blockaddress(@test_indirectbr_phi, %End), ptr %address
  indirectbr ptr %indirect.goto.dest2, [label %Tail, label %End]

Tail:
  %p = phi i32[1,%Header], [2, %TBB]
  %r = call i32 @callee(ptr %a, i32 %v, i32 %p)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_cond_no_effect
;CHECK-NOT: Header.split:
;CHECK-NOT: TBB.split:
;CHECK-LABEL: Tail:
;CHECK: %r = call i32 @callee(ptr %a, i32 %v, i32 0)
;CHECK: ret i32 %r
define i32 @test_cond_no_effect(ptr %a, i32 %v) {
Entry:
  %tobool1 = icmp eq ptr %a, null
  br i1 %tobool1, label %Header, label %End

Header:
  br i1 undef, label %Tail, label %TBB

TBB:
  br i1 undef, label %Tail, label %End

Tail:
  %r = call i32 @callee(ptr %a, i32 %v, i32 0)
  ret i32 %r

End:
  ret i32 %v
}

;CHECK-LABEL: @test_unreachable
;CHECK-LABEL: Header.split:
;CHECK: %[[CALL1:.*]] = call i32 @callee(ptr %a, i32 %v, i32 10)
;CHECK-LABEL: TBB.split:
;CHECK: %[[CALL2:.*]] = call i32 @callee(ptr %a, i32 1, i32 %p)
;CHECK-LABEL: Tail
;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
;CHECK: ret i32 %[[MERGED]]
define i32 @test_unreachable(ptr %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(ptr %a, i32 %v, i32 %p)
  ret i32 %r
End:
  ret i32 %v
}

define i32 @callee(ptr %a, i32 %v, i32 %p) {
entry:
  %c = icmp ne ptr %a, null
  br i1 %c, label %BB1, label %BB2

BB1:
  call void @dummy(ptr %a, i32 %p)
  br label %End

BB2:
  call void @dummy2(i32 %v, i32 %p)
  br label %End

End:
  ret i32 %p
}

declare void @dummy(ptr, i32)
declare void @dummy2(i32, i32)

; Make sure we remove the non-nullness on constant paramater.
;
;CHECK-LABEL: @caller2
;CHECK-LABEL: Top1.split:
;CHECK: call i32 @callee(ptr inttoptr (i64 4643 to ptr)
define void @caller2(i32 %c, ptr %a_elt, ptr %b_elt) {
entry:
  br label %Top0

Top0:
  %tobool1 = icmp eq ptr %a_elt, inttoptr (i64 4643 to  ptr)
  br i1 %tobool1, label %Top1, label %NextCond

Top1:
  %tobool2 = icmp ne ptr %a_elt, null
  br i1 %tobool2, label %CallSiteBB, label %NextCond

NextCond:
  %cmp = icmp ne ptr %b_elt, null
  br i1 %cmp, label %CallSiteBB, label %End

CallSiteBB:
  call i32 @callee(ptr %a_elt, i32 %c, i32 %c)
  br label %End

End:
  ret void
}

; CHECK-LABEL: i32 @test_multiple_phis(
; CHECK:      Header.split:
; CHECK-NEXT:   %r2 = call i32 @callee(ptr null, i32 1, i32 5)
; CHECK-NEXT:   br label %Tail

; CHECK:      TBB.split:
; CHECK-NEXT:   %r1 = call i32 @callee(ptr null, i32 2, i32 10)
; CHECK-NEXT:   br label %Tail

; CHECK:        Tail:
; CHECK-NEXT:   %phi.call = phi i32 [ %r1, %TBB.split ], [ %r2, %Header.split ]
; CHECK-NEXT:   %p.0 = phi i32 [ 0, %Header.split ], [ 99, %TBB.split ]
; CHECK-NEXT:   %res = add i32 %phi.call, %p.0
; CHECK-NEXT:   ret i32 %phi.call
;
define i32 @test_multiple_phis(i1 %c.1) {
Header:
  br i1 %c.1, label %Tail, label %TBB

TBB:
  br label %Tail

Tail:
  %p.0 = phi i32 [0, %Header], [99, %TBB]
  %p.1 = phi i32[1, %Header], [2, %TBB]
  %p.2 = phi i32 [5, %Header], [10, %TBB]
  %r = call i32 @callee(ptr null, i32 %p.1, i32 %p.2)
  %res = add i32 %r, %p.0
  ret i32 %r

End:
  ret i32 10
}