1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -ipsccp < %s | FileCheck %s
3
4declare void @BB0_f()
5declare void @BB1_f()
6
7; Make sure we can eliminate what is in BB0 as we know that the indirectbr is going to BB1.
8;
9define void @indbrtest1() {
10; CHECK-LABEL: @indbrtest1(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    br label [[BB1:%.*]]
13; CHECK:       BB1:
14; CHECK-NEXT:    call void @BB1_f()
15; CHECK-NEXT:    ret void
16;
17entry:
18  indirectbr i8* blockaddress(@indbrtest1, %BB1), [label %BB0, label %BB1]
19BB0:
20  call void @BB0_f()
21  br label %BB1
22BB1:
23  call void @BB1_f()
24  ret void
25}
26
27; Make sure we can eliminate what is in BB0 as we know that the indirectbr is going to BB1
28; by looking through the casts. The casts should be folded away when they are visited
29; before the indirectbr instruction.
30;
31define void @indbrtest2() {
32; CHECK-LABEL: @indbrtest2(
33; CHECK-NEXT:  entry:
34; CHECK-NEXT:    br label [[BB1:%.*]]
35; CHECK:       BB1:
36; CHECK-NEXT:    call void @BB1_f()
37; CHECK-NEXT:    ret void
38;
39entry:
40  %a = ptrtoint i8* blockaddress(@indbrtest2, %BB1) to i64
41  %b = inttoptr i64 %a to i8*
42  %c = bitcast i8* %b to i8*
43  indirectbr i8* %b, [label %BB0, label %BB1]
44BB0:
45  call void @BB0_f()
46  br label %BB1
47BB1:
48  call void @BB1_f()
49  ret void
50}
51
52; Make sure we can not eliminate BB0 as we do not know the target of the indirectbr.
53
54define void @indbrtest3(i8** %Q) {
55; CHECK-LABEL: @indbrtest3(
56; CHECK-NEXT:  entry:
57; CHECK-NEXT:    [[T:%.*]] = load i8*, i8** [[Q:%.*]], align 8
58; CHECK-NEXT:    indirectbr i8* [[T]], [label [[BB0:%.*]], label %BB1]
59; CHECK:       BB0:
60; CHECK-NEXT:    call void @BB0_f()
61; CHECK-NEXT:    br label [[BB1:%.*]]
62; CHECK:       BB1:
63; CHECK-NEXT:    call void @BB1_f()
64; CHECK-NEXT:    ret void
65;
66entry:
67  %t = load i8*, i8** %Q
68  indirectbr i8* %t, [label %BB0, label %BB1]
69BB0:
70  call void @BB0_f()
71  br label %BB1
72BB1:
73  call void @BB1_f()
74  ret void
75}
76
77; Make sure we eliminate BB1 as we pick the first successor on undef.
78
79define void @indbrtest4(i8** %Q) {
80; CHECK-LABEL: @indbrtest4(
81; CHECK-NEXT:  entry:
82; CHECK-NEXT:    br label [[BB0:%.*]]
83; CHECK:       BB0:
84; CHECK-NEXT:    call void @BB0_f()
85; CHECK-NEXT:    ret void
86;
87entry:
88  indirectbr i8* undef, [label %BB0, label %BB1]
89BB0:
90  call void @BB0_f()
91  ret void
92BB1:
93  call void @BB1_f()
94  ret void
95}
96
97define internal i32 @indbrtest5(i1 %c) {
98; CHECK-LABEL: @indbrtest5(
99; CHECK-NEXT:  entry:
100; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
101; CHECK:       bb1:
102; CHECK-NEXT:    br label [[BRANCH_BLOCK:%.*]]
103; CHECK:       bb2:
104; CHECK-NEXT:    br label [[BRANCH_BLOCK]]
105; CHECK:       branch.block:
106; CHECK-NEXT:    [[ADDR:%.*]] = phi i8* [ blockaddress(@indbrtest5, [[TARGET1:%.*]]), [[BB1]] ], [ blockaddress(@indbrtest5, [[TARGET2:%.*]]), [[BB2]] ]
107; CHECK-NEXT:    indirectbr i8* [[ADDR]], [label [[TARGET1]], label %target2]
108; CHECK:       target1:
109; CHECK-NEXT:    br label [[TARGET2]]
110; CHECK:       target2:
111; CHECK-NEXT:    ret i32 undef
112;
113entry:
114  br i1 %c, label %bb1, label %bb2
115
116bb1:
117  br label %branch.block
118
119
120bb2:
121  br label %branch.block
122
123branch.block:
124  %addr = phi i8* [blockaddress(@indbrtest5, %target1), %bb1], [blockaddress(@indbrtest5, %target2), %bb2]
125  indirectbr i8* %addr, [label %target1, label %target2]
126
127target1:
128  br label %target2
129
130target2:
131  ret i32 10
132}
133
134
135define i32 @indbrtest5_callee(i1 %c) {
136; CHECK-LABEL: @indbrtest5_callee(
137; CHECK-NEXT:    [[R:%.*]] = call i32 @indbrtest5(i1 [[C:%.*]])
138; CHECK-NEXT:    ret i32 10
139;
140  %r = call i32 @indbrtest5(i1 %c)
141  ret i32 %r
142}
143
144define i32 @indbr_duplicate_successors_phi(i1 %c, i32 %x) {
145; CHECK-LABEL: @indbr_duplicate_successors_phi(
146; CHECK-NEXT:  entry:
147; CHECK-NEXT:    br i1 [[C:%.*]], label [[INDBR:%.*]], label [[BB0:%.*]]
148; CHECK:       indbr:
149; CHECK-NEXT:    br label [[BB0]]
150; CHECK:       BB0:
151; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[X:%.*]], [[ENTRY:%.*]] ], [ 0, [[INDBR]] ]
152; CHECK-NEXT:    ret i32 [[PHI]]
153;
154entry:
155  br i1 %c, label %indbr, label %BB0
156
157indbr:
158  indirectbr i8* blockaddress(@indbr_duplicate_successors_phi, %BB0), [label %BB0, label %BB0, label %BB1]
159
160BB0:
161  %phi = phi i32 [ %x, %entry ], [ 0, %indbr ], [ 0, %indbr ]
162  ret i32 %phi
163
164BB1:
165  ret i32 0
166}
167