; Test that the inliner doesn't leave around dead allocas, and that it folds
; uncond branches away after it is done specializing.

; RUN: opt < %s -inline -S | FileCheck %s

@A = weak global i32 0		; <i32*> [#uses=1]
@B = weak global i32 0		; <i32*> [#uses=1]
@C = weak global i32 0		; <i32*> [#uses=1]

define internal fastcc void @foo(i32 %X) {
entry:
	%ALL = alloca i32, align 4		; <i32*> [#uses=1]
	%tmp1 = and i32 %X, 1		; <i32> [#uses=1]
	%tmp1.upgrd.1 = icmp eq i32 %tmp1, 0		; <i1> [#uses=1]
	br i1 %tmp1.upgrd.1, label %cond_next, label %cond_true

cond_true:		; preds = %entry
	store i32 1, i32* @A
	br label %cond_next

cond_next:		; preds = %cond_true, %entry
	%tmp4 = and i32 %X, 2		; <i32> [#uses=1]
	%tmp4.upgrd.2 = icmp eq i32 %tmp4, 0		; <i1> [#uses=1]
	br i1 %tmp4.upgrd.2, label %cond_next7, label %cond_true5

cond_true5:		; preds = %cond_next
	store i32 1, i32* @B
	br label %cond_next7

cond_next7:		; preds = %cond_true5, %cond_next
	%tmp10 = and i32 %X, 4		; <i32> [#uses=1]
	%tmp10.upgrd.3 = icmp eq i32 %tmp10, 0		; <i1> [#uses=1]
	br i1 %tmp10.upgrd.3, label %cond_next13, label %cond_true11

cond_true11:		; preds = %cond_next7
	store i32 1, i32* @C
	br label %cond_next13

cond_next13:		; preds = %cond_true11, %cond_next7
	%tmp16 = and i32 %X, 8		; <i32> [#uses=1]
	%tmp16.upgrd.4 = icmp eq i32 %tmp16, 0		; <i1> [#uses=1]
	br i1 %tmp16.upgrd.4, label %UnifiedReturnBlock, label %cond_true17

cond_true17:		; preds = %cond_next13
	call void @ext( i32* %ALL )
	ret void

UnifiedReturnBlock:		; preds = %cond_next13
	ret void
}

declare void @ext(i32*)

define void @test() {
; CHECK-LABEL: @test(
; CHECK-NOT: ret
;
; FIXME: This should be a CHECK-NOT, but currently we have a bug that causes us
; to not nuke unused allocas.
; CHECK: alloca
; CHECK-NOT: ret
;
; No branches should survive the inliner's cleanup.
; CHECK-NOT: br
; CHECK: ret void

entry:
	tail call fastcc void @foo( i32 1 )
	tail call fastcc void @foo( i32 2 )
	tail call fastcc void @foo( i32 3 )
	tail call fastcc void @foo( i32 8 )
	ret void
}

declare void @f(i32 %x)

define void @inner2(i32 %x, i32 %y, i32 %z, i1 %b) {
entry:
  %cmp1 = icmp ne i32 %x, 0
  br i1 %cmp1, label %then1, label %end1

then1:
  call void @f(i32 %x)
  br label %end1

end1:
  %x2 = and i32 %x, %z
  %cmp2 = icmp sgt i32 %x2, 1
  br i1 %cmp2, label %then2, label %end2

then2:
  call void @f(i32 %x2)
  br label %end2

end2:
  %y2 = or i32 %y, %z
  %cmp3 = icmp sgt i32 %y2, 0
  br i1 %cmp3, label %then3, label %end3

then3:
  call void @f(i32 %y2)
  br label %end3

end3:
  br i1 %b, label %end3.1, label %end3.2

end3.1:
  %x3.1 = or i32 %x, 10
  br label %end3.3

end3.2:
  %x3.2 = or i32 %x, 10
  br label %end3.3

end3.3:
  %x3.3 = phi i32 [ %x3.1, %end3.1 ], [ %x3.2, %end3.2 ]
  %cmp4 = icmp slt i32 %x3.3, 1
  br i1 %cmp4, label %then4, label %end4

then4:
  call void @f(i32 %x3.3)
  br label %end4

end4:
  ret void
}

define void @outer2(i32 %z, i1 %b) {
; Ensure that after inlining, none of the blocks with a call to @f actually
; make it through inlining.
; CHECK-LABEL: define void @outer2(
; CHECK-NOT: call
; CHECK: ret void

entry:
  call void @inner2(i32 0, i32 -1, i32 %z, i1 %b)
  ret void
}

define void @PR12470_inner(i16 signext %p1) nounwind uwtable {
entry:
  br i1 undef, label %cond.true, label %cond.false

cond.true:
  br label %cond.end

cond.false:
  %conv = sext i16 %p1 to i32
  br label %cond.end

cond.end:
  %cond = phi i32 [ undef, %cond.true ], [ 0, %cond.false ]
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.end5, label %if.then

if.then:
  ret void

if.end5:
  ret void
}

define void @PR12470_outer() {
; This previously crashed during inliner cleanup and folding inner return
; instructions. Check that we don't crash and we produce a function with a single
; return instruction due to merging the returns of the inlined function.
; CHECK-LABEL: define void @PR12470_outer(
; CHECK-NOT: call
; CHECK: ret void
; CHECK-NOT: ret void
; CHECK: }

entry:
  call void @PR12470_inner(i16 signext 1)
  ret void
}

define void @crasher_inner() nounwind uwtable {
entry:
  br i1 false, label %for.end28, label %for.body6

for.body6:
  br i1 undef, label %for.body6, label %for.cond12.for.inc26_crit_edge

for.cond12.for.inc26_crit_edge:
  br label %for.body6.1

for.end28:
  ret void

for.body6.1:
  br i1 undef, label %for.body6.1, label %for.cond12.for.inc26_crit_edge.1

for.cond12.for.inc26_crit_edge.1:
  br label %for.body6.2

for.body6.2:
  br i1 undef, label %for.body6.2, label %for.cond12.for.inc26_crit_edge.2

for.cond12.for.inc26_crit_edge.2:
  br label %for.end28
}

define void @crasher_outer() {
; CHECK-LABEL: @crasher_outer(
; CHECK-NOT: call
; CHECK: ret void
; CHECK-NOT: ret
; CHECK: }
entry:
  tail call void @crasher_inner()
  ret void
}
