xref: /llvm-project/llvm/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll (revision 53dc0f107877acad44824b1426986c7f88f4bc50)
1; RUN: opt < %s -passes=tailcallelim -verify-dom-info -S | FileCheck %s
2; PR7328
3; PR7506
4define i32 @test1_constants(i32 %x) {
5entry:
6  %cond = icmp ugt i32 %x, 0                      ; <i1> [#uses=1]
7  br i1 %cond, label %return, label %body
8
9body:                                             ; preds = %entry
10  %y = add i32 %x, 1                              ; <i32> [#uses=1]
11  %recurse = call i32 @test1_constants(i32 %y)        ; <i32> [#uses=0]
12  ret i32 0
13
14return:                                           ; preds = %entry
15  ret i32 1
16}
17
18; CHECK-LABEL: define i32 @test1_constants(
19; CHECK: tailrecurse:
20; CHECK: %ret.tr = phi i32 [ poison, %entry ], [ %current.ret.tr, %body ]
21; CHECK: %ret.known.tr = phi i1 [ false, %entry ], [ true, %body ]
22; CHECK: body:
23; CHECK-NOT: %recurse
24; CHECK: %current.ret.tr = select i1 %ret.known.tr, i32 %ret.tr, i32 0
25; CHECK-NOT: ret
26; CHECK: return:
27; CHECK: %current.ret.tr1 = select i1 %ret.known.tr, i32 %ret.tr, i32 1
28; CHECK: ret i32 %current.ret.tr1
29
30define i32 @test2_non_constants(i32 %x) {
31entry:
32  %cond = icmp ugt i32 %x, 0
33  br i1 %cond, label %return, label %body
34
35body:
36  %y = add i32 %x, 1
37  %helper1 = call i32 @test2_helper()
38  %recurse = call i32 @test2_non_constants(i32 %y)
39  ret i32 %helper1
40
41return:
42  %helper2 = call i32 @test2_helper()
43  ret i32 %helper2
44}
45
46declare i32 @test2_helper()
47
48; CHECK-LABEL: define i32 @test2_non_constants(
49; CHECK: tailrecurse:
50; CHECK: %ret.tr = phi i32 [ poison, %entry ], [ %current.ret.tr, %body ]
51; CHECK: %ret.known.tr = phi i1 [ false, %entry ], [ true, %body ]
52; CHECK: body:
53; CHECK-NOT: %recurse
54; CHECK: %current.ret.tr = select i1 %ret.known.tr, i32 %ret.tr, i32 %helper1
55; CHECK-NOT: ret
56; CHECK: return:
57; CHECK: %current.ret.tr1 = select i1 %ret.known.tr, i32 %ret.tr, i32 %helper2
58; CHECK: ret i32 %current.ret.tr1
59
60define i32 @test3_mixed(i32 %x) {
61entry:
62  switch i32 %x, label %default [
63    i32 0, label %case0
64    i32 1, label %case1
65    i32 2, label %case2
66  ]
67
68case0:
69  %helper1 = call i32 @test3_helper()
70  br label %return
71
72case1:
73  %y1 = add i32 %x, -1
74  %recurse1 = call i32 @test3_mixed(i32 %y1)
75  br label %return
76
77case2:
78  %y2 = add i32 %x, -1
79  %helper2 = call i32 @test3_helper()
80  %recurse2 = call i32 @test3_mixed(i32 %y2)
81  br label %return
82
83default:
84  %y3 = urem i32 %x, 3
85  %recurse3 = call i32 @test3_mixed(i32 %y3)
86  br label %return
87
88return:
89  %retval = phi i32 [ %recurse3, %default ], [ %helper2, %case2 ], [ 9, %case1 ], [ %helper1, %case0 ]
90  ret i32 %retval
91}
92
93declare i32 @test3_helper()
94
95; CHECK-LABEL: define i32 @test3_mixed(
96; CHECK: tailrecurse:
97; CHECK: %ret.tr = phi i32 [ poison, %entry ], [ %current.ret.tr, %case1 ], [ %current.ret.tr1, %case2 ], [ %ret.tr, %default ]
98; CHECK: %ret.known.tr = phi i1 [ false, %entry ], [ true, %case1 ], [ true, %case2 ], [ %ret.known.tr, %default ]
99; CHECK: case1:
100; CHECK-NOT: %recurse
101; CHECK: %current.ret.tr = select i1 %ret.known.tr, i32 %ret.tr, i32 9
102; CHECK: br label %tailrecurse
103; CHECK: case2:
104; CHECK-NOT: %recurse
105; CHECK: %current.ret.tr1 = select i1 %ret.known.tr, i32 %ret.tr, i32 %helper2
106; CHECK: br label %tailrecurse
107; CHECK: default:
108; CHECK-NOT: %recurse
109; CHECK: br label %tailrecurse
110; CHECK: return:
111; CHECK: %current.ret.tr2 = select i1 %ret.known.tr, i32 %ret.tr, i32 %helper1
112; CHECK: ret i32 %current.ret.tr2
113