1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
3; RUN: opt -S -codegenprepare %s -mtriple=x86_64-apple-darwin -o - | FileCheck %s --check-prefix OPT
4
5; Teach CGP to dup returns to enable tail call optimization.
6; rdar://9147433
7
8define i32 @foo(i32 %x) nounwind ssp {
9; CHECK-LABEL: foo:
10entry:
11  switch i32 %x, label %return [
12    i32 1, label %sw.bb
13    i32 2, label %sw.bb1
14    i32 3, label %sw.bb3
15    i32 4, label %sw.bb5
16    i32 5, label %sw.bb7
17    i32 6, label %sw.bb9
18  ]
19
20sw.bb:                                            ; preds = %entry
21; CHECK: jmp _f1
22  %call = tail call i32 @f1() nounwind
23  br label %return
24
25sw.bb1:                                           ; preds = %entry
26; CHECK: jmp _f2
27  %call2 = tail call i32 @f2() nounwind
28  br label %return
29
30sw.bb3:                                           ; preds = %entry
31; CHECK: jmp _f3
32  %call4 = tail call i32 @f3() nounwind
33  br label %return
34
35sw.bb5:                                           ; preds = %entry
36; CHECK: jmp _f4
37  %call6 = tail call i32 @f4() nounwind
38  br label %return
39
40sw.bb7:                                           ; preds = %entry
41; CHECK: jmp _f5
42  %call8 = tail call i32 @f5() nounwind
43  br label %return
44
45sw.bb9:                                           ; preds = %entry
46; CHECK: jmp _f6
47  %call10 = tail call i32 @f6() nounwind
48  br label %return
49
50return:                                           ; preds = %entry, %sw.bb9, %sw.bb7, %sw.bb5, %sw.bb3, %sw.bb1, %sw.bb
51  %retval.0 = phi i32 [ %call10, %sw.bb9 ], [ %call8, %sw.bb7 ], [ %call6, %sw.bb5 ], [ %call4, %sw.bb3 ], [ %call2, %sw.bb1 ], [ %call, %sw.bb ], [ 0, %entry ]
52  ret i32 %retval.0
53}
54
55declare i32 @f1()
56
57declare i32 @f2()
58
59declare i32 @f3()
60
61declare i32 @f4()
62
63declare i32 @f5()
64
65declare i32 @f6()
66
67; rdar://11958338
68%0 = type opaque
69
70declare i8* @bar(i8*) uwtable optsize noinline ssp
71
72define hidden %0* @thingWithValue(i8* %self) uwtable ssp {
73entry:
74; CHECK-LABEL: thingWithValue:
75; CHECK: jmp _bar
76  br i1 undef, label %if.then.i, label %if.else.i
77
78if.then.i:                                        ; preds = %entry
79  br label %someThingWithValue.exit
80
81if.else.i:                                        ; preds = %entry
82  %call4.i = tail call i8* @bar(i8* undef) optsize
83  br label %someThingWithValue.exit
84
85someThingWithValue.exit:                          ; preds = %if.else.i, %if.then.i
86  %retval.0.in.i = phi i8* [ undef, %if.then.i ], [ %call4.i, %if.else.i ]
87  %retval.0.i = bitcast i8* %retval.0.in.i to %0*
88  ret %0* %retval.0.i
89}
90
91
92; Correctly handle zext returns.
93declare zeroext i1 @foo_i1()
94
95; CHECK-LABEL: zext_i1
96; CHECK: jmp _foo_i1
97define zeroext i1 @zext_i1(i1 %k) {
98entry:
99  br i1 %k, label %land.end, label %land.rhs
100
101land.rhs:                                         ; preds = %entry
102  %call1 = tail call zeroext i1 @foo_i1()
103  br label %land.end
104
105land.end:                                         ; preds = %entry, %land.rhs
106  %0 = phi i1 [ false, %entry ], [ %call1, %land.rhs ]
107  ret i1 %0
108}
109
110; We need to look through bitcasts when looking for tail calls in phi incoming
111; values.
112declare i32* @g_ret32()
113define i8* @f_ret8(i8* %obj) nounwind {
114; OPT-LABEL: @f_ret8(
115; OPT-NEXT:  entry:
116; OPT-NEXT:    [[CMP:%.*]] = icmp eq i8* [[OBJ:%.*]], null
117; OPT-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[IF_THEN:%.*]]
118; OPT:       if.then:
119; OPT-NEXT:    [[PTR:%.*]] = tail call i32* @g_ret32()
120; OPT-NEXT:    [[CASTED:%.*]] = bitcast i32* [[PTR]] to i8*
121; OPT-NEXT:    ret i8* [[CASTED]]
122; OPT:       return:
123; OPT-NEXT:    ret i8* [[OBJ]]
124;
125; CHECK-LABEL: f_ret8:
126; CHECK:       ## %bb.0: ## %entry
127; CHECK-NEXT:    testq %rdi, %rdi
128; CHECK-NEXT:    je LBB3_1
129; CHECK-NEXT:  ## %bb.2: ## %if.then
130; CHECK-NEXT:    jmp _g_ret32 ## TAILCALL
131; CHECK-NEXT:  LBB3_1: ## %return
132; CHECK-NEXT:    movq %rdi, %rax
133; CHECK-NEXT:    retq
134entry:
135  %cmp = icmp eq i8* %obj, null
136  br i1 %cmp, label %return, label %if.then
137
138if.then:
139  %ptr = tail call i32* @g_ret32()
140  %casted = bitcast i32* %ptr to i8*
141  br label %return
142
143return:
144  %retval = phi i8* [ %casted, %if.then ], [ %obj, %entry ]
145  ret i8* %retval
146}
147