xref: /llvm-project/llvm/test/CodeGen/PowerPC/ctrloops-hot-exit.ll (revision 427fb35192f1f7bb694a5910b05abc5925a798b2)
1; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s
2
3; If there is an exit edge known to be frequently taken,
4; we should not transform this loop.
5
6; A loop having a hot exit edge (exit in false branch)
7define signext i64 @func() {
8; CHECK: @func
9; CHECK-NOT: mtctr
10; CHECK-NOT: bdnz
11
12entry:
13  %a = alloca [1000 x i32], align 4
14  br label %for.body
15
16for.body:
17  %i.013 = phi i64 [ 0, %entry ], [ %inc, %if.end ]
18  %b.012 = phi i64 [ 0, %entry ], [ %xor, %if.end ]
19  %arrayidx = getelementptr inbounds [1000 x i32], ptr %a, i64 0, i64 %i.013
20  %0 = load i32, ptr %arrayidx, align 4
21  %tobool = icmp eq i32 %0, 0
22  br i1 %tobool, label %if.end, label %cleanup, !prof !1
23
24if.end:
25  %xor = xor i64 %i.013, %b.012
26  %inc = add nuw nsw i64 %i.013, 1
27  %cmp = icmp ult i64 %inc, 1000
28  br i1 %cmp, label %for.body, label %cleanup
29
30cleanup:
31  %res = phi i64 [ %b.012, %for.body ], [ %xor, %if.end ]
32  ret i64 %res
33}
34
35; A loop having a cold exit edge (exit in false branch)
36define signext i64 @func2() {
37; CHECK: @func2
38; CHECK: mtctr
39; CHECK: bdnz
40
41entry:
42  %a = alloca [1000 x i32], align 4
43  br label %for.body
44
45for.body:
46  %i.013 = phi i64 [ 0, %entry ], [ %inc, %if.end ]
47  %b.012 = phi i64 [ 0, %entry ], [ %xor, %if.end ]
48  %arrayidx = getelementptr inbounds [1000 x i32], ptr %a, i64 0, i64 %i.013
49  %0 = load i32, ptr %arrayidx, align 4
50  %tobool = icmp eq i32 %0, 0
51  br i1 %tobool, label %if.end, label %cleanup, !prof !2
52
53if.end:
54  %xor = xor i64 %i.013, %b.012
55  %inc = add nuw nsw i64 %i.013, 1
56  %cmp = icmp ult i64 %inc, 1000
57  br i1 %cmp, label %for.body, label %cleanup
58
59cleanup:
60  %res = phi i64 [ %b.012, %for.body ], [ %xor, %if.end ]
61  ret i64 %res
62}
63
64; A loop having an exit edge without profile data  (exit in false branch)
65define signext i64 @func3() {
66; CHECK: @func3
67; CHECK: mtctr
68; CHECK: bdnz
69
70entry:
71  %a = alloca [1000 x i32], align 4
72  br label %for.body
73
74for.body:
75  %i.013 = phi i64 [ 0, %entry ], [ %inc, %if.end ]
76  %b.012 = phi i64 [ 0, %entry ], [ %xor, %if.end ]
77  %arrayidx = getelementptr inbounds [1000 x i32], ptr %a, i64 0, i64 %i.013
78  %0 = load i32, ptr %arrayidx, align 4
79  %tobool = icmp eq i32 %0, 0
80  br i1 %tobool, label %if.end, label %cleanup
81
82if.end:
83  %xor = xor i64 %i.013, %b.012
84  %inc = add nuw nsw i64 %i.013, 1
85  %cmp = icmp ult i64 %inc, 1000
86  br i1 %cmp, label %for.body, label %cleanup
87
88cleanup:
89  %res = phi i64 [ %b.012, %for.body ], [ %xor, %if.end ]
90  ret i64 %res
91}
92
93; A loop having a hot exit edge (exit in true branch)
94define signext i64 @func4() {
95; CHECK: @func4
96; CHECK-NOT: mtctr
97; CHECK-NOT: bdnz
98
99entry:
100  %a = alloca [1000 x i32], align 4
101  br label %for.body
102
103for.body:
104  %i.013 = phi i64 [ 0, %entry ], [ %inc, %if.end ]
105  %b.012 = phi i64 [ 0, %entry ], [ %xor, %if.end ]
106  %arrayidx = getelementptr inbounds [1000 x i32], ptr %a, i64 0, i64 %i.013
107  %0 = load i32, ptr %arrayidx, align 4
108  %tobool = icmp ne i32 %0, 0
109  br i1 %tobool, label %cleanup, label %if.end, !prof !2
110
111if.end:
112  %xor = xor i64 %i.013, %b.012
113  %inc = add nuw nsw i64 %i.013, 1
114  %cmp = icmp ult i64 %inc, 1000
115  br i1 %cmp, label %for.body, label %cleanup
116
117cleanup:
118  %res = phi i64 [ %b.012, %for.body ], [ %xor, %if.end ]
119  ret i64 %res
120}
121
122; A loop having a cold exit edge (exit in true branch)
123define signext i64 @func5() {
124; CHECK: @func5
125; CHECK: mtctr
126; CHECK: bdnz
127
128entry:
129  %a = alloca [1000 x i32], align 4
130  br label %for.body
131
132for.body:
133  %i.013 = phi i64 [ 0, %entry ], [ %inc, %if.end ]
134  %b.012 = phi i64 [ 0, %entry ], [ %xor, %if.end ]
135  %arrayidx = getelementptr inbounds [1000 x i32], ptr %a, i64 0, i64 %i.013
136  %0 = load i32, ptr %arrayidx, align 4
137  %tobool = icmp ne i32 %0, 0
138  br i1 %tobool, label %cleanup, label %if.end, !prof !1
139
140if.end:
141  %xor = xor i64 %i.013, %b.012
142  %inc = add nuw nsw i64 %i.013, 1
143  %cmp = icmp ult i64 %inc, 1000
144  br i1 %cmp, label %for.body, label %cleanup
145
146cleanup:
147  %res = phi i64 [ %b.012, %for.body ], [ %xor, %if.end ]
148  ret i64 %res
149}
150
151; A loop having an exit edge without profile data  (exit in true branch)
152define signext i64 @func6() {
153; CHECK: @func6
154; CHECK: mtctr
155; CHECK: bdnz
156
157entry:
158  %a = alloca [1000 x i32], align 4
159  br label %for.body
160
161for.body:
162  %i.013 = phi i64 [ 0, %entry ], [ %inc, %if.end ]
163  %b.012 = phi i64 [ 0, %entry ], [ %xor, %if.end ]
164  %arrayidx = getelementptr inbounds [1000 x i32], ptr %a, i64 0, i64 %i.013
165  %0 = load i32, ptr %arrayidx, align 4
166  %tobool = icmp ne i32 %0, 0
167  br i1 %tobool, label %cleanup, label %if.end
168
169if.end:
170  %xor = xor i64 %i.013, %b.012
171  %inc = add nuw nsw i64 %i.013, 1
172  %cmp = icmp ult i64 %inc, 1000
173  br i1 %cmp, label %for.body, label %cleanup
174
175cleanup:
176  %res = phi i64 [ %b.012, %for.body ], [ %xor, %if.end ]
177  ret i64 %res
178}
179
180!1 = !{!"branch_weights", i32 1, i32 2000}
181!2 = !{!"branch_weights", i32 2000, i32 1}
182