1; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
2
3
4@gvar = external global i32
5
6; dupbb has two predecessors, p1 and p2. p1 is hot, p2 is cold. So dupbb
7; should be placed after p1, and not duplicated into p2.
8;
9; CHECK-LABEL: test1
10; CHECK:       %p1
11; CHECK:       .LBB0_4: # %dupbb
12; CHECK:       %p2
13; CHECK:       jmp .LBB0_4
14
15define void @test1(i32* %p) !prof !1 {
16entry:
17  br label %header
18
19header:
20  %call = call zeroext i1 @a()
21  br i1 %call, label %p1, label %p2, !prof !2
22
23p1:
24  call void @b()
25  br label %dupbb
26
27p2:
28  call void @c()
29  br label %dupbb
30
31dupbb:
32  %cond = icmp eq i32* @gvar, %p
33  br i1 %cond, label %header, label %latch, !prof !3
34
35latch:
36  %call3 = call zeroext i1 @a()
37  br i1 %call3, label %header, label %end, !prof !2
38
39end:
40  ret void
41}
42
43
44; dupbb has four predecessors p1, p2, p3 and p4. p1 and p2 are hot, p3 and  p4
45; are cold. So dupbb should be placed after p1, duplicated into p2. p3 and p4
46; should jump to dupbb.
47;
48; CHECK-LABEL: test2
49; CHECK:       %p1
50; CHECK:       .LBB1_8: # %dupbb
51;
52; CHECK:       %p2
53; CHECK:       callq c
54; CHECK-NEXT:  cmpq
55; CHECK-NEXT:  je
56; CHECK-NEXT:  jmp
57;
58; CHECK:       %p3
59; CHECK:       jmp .LBB1_8
60; CHECK:       %p4
61; CHECK:       jmp .LBB1_8
62
63define void @test2(i32* %p) !prof !1 {
64entry:
65  br label %header
66
67header:
68  %call = call zeroext i1 @a()
69  br i1 %call, label %bb1, label %bb2, !prof !2
70
71bb1:
72  %call1 = call zeroext i1 @a()
73  br i1 %call1, label %p1, label %p2, !prof !4
74
75bb2:
76  %call2 = call zeroext i1 @a()
77  br i1 %call2, label %p3, label %p4, !prof !4
78
79p1:
80  call void @b()
81  br label %dupbb
82
83p2:
84  call void @c()
85  br label %dupbb
86
87p3:
88  call void @d()
89  br label %dupbb
90
91p4:
92  call void @e()
93  br label %dupbb
94
95dupbb:
96  %cond = icmp eq i32* @gvar, %p
97  br i1 %cond, label %bb3, label %bb4, !prof !4
98
99bb3:
100  call void @b()
101  br label %bb4
102
103bb4:
104  %call4 = call zeroext i1 @a()
105  br i1 %call4, label %header, label %latch, !prof !3
106
107latch:
108  %call3 = call zeroext i1 @a()
109  br i1 %call3, label %header, label %end, !prof !2
110
111end:
112  ret void
113}
114
115
116; dupbb has three predecessors p1, p2 and p3. p3 has two successors, so dupbb
117; can't be duplicated into p3, but it should not block it to be duplicated into
118; other predecessors.
119;
120; CHECK-LABEL: test3
121; CHECK:       %p1
122; CHECK:       .LBB2_6: # %dupbb
123;
124; CHECK:       %p2
125; CHECK:       callq c
126; CHECK:       cmpq
127; CHECK-NEXT:  je
128; CHECK-NEXT:  jmp
129;
130; CHECK:       %p3
131; CHECK:       jne .LBB2_6
132
133define void @test3(i32* %p) !prof !1 {
134entry:
135  br label %header
136
137header:
138  %call = call zeroext i1 @a()
139  br i1 %call, label %bb1, label %p3, !prof !2
140
141bb1:
142  %call1 = call zeroext i1 @a()
143  br i1 %call1, label %p1, label %p2, !prof !4
144
145p1:
146  call void @b()
147  br label %dupbb
148
149p2:
150  call void @c()
151  br label %dupbb
152
153p3:
154  %call2 = call zeroext i1 @a()
155  br i1 %call2, label %dupbb, label %bb4, !prof !4
156
157dupbb:
158  %cond = icmp eq i32* @gvar, %p
159  br i1 %cond, label %bb3, label %bb4, !prof !4
160
161bb3:
162  call void @b()
163  br label %bb4
164
165bb4:
166  %call4 = call zeroext i1 @a()
167  br i1 %call4, label %header, label %latch, !prof !3
168
169latch:
170  %call3 = call zeroext i1 @a()
171  br i1 %call3, label %header, label %end, !prof !2
172
173end:
174  ret void
175}
176
177declare zeroext i1 @a()
178declare void @b()
179declare void @c()
180declare void @d()
181declare void @e()
182declare void @f()
183
184!1 = !{!"function_entry_count", i64 1000}
185!2 = !{!"branch_weights", i32 100, i32 1}
186!3 = !{!"branch_weights", i32 1, i32 100}
187!4 = !{!"branch_weights", i32 60, i32 40}
188