xref: /llvm-project/llvm/test/CodeGen/X86/move_latch_to_loop_top.ll (revision 2f448bf509432c1a19ec46ab8cbc7353c03c6280)
1; RUN: llc  -mcpu=corei7 -mtriple=x86_64-linux < %s | FileCheck %s
2
3; The block latch should be moved before header.
4;CHECK-LABEL: test1:
5;CHECK:       %latch
6;CHECK:       %header
7;CHECK:       %false
8define i32 @test1(ptr %p) {
9entry:
10  br label %header
11
12header:
13  %x1 = phi i64 [0, %entry], [%x2, %latch]
14  %count1 = phi i32 [0, %entry], [%count4, %latch]
15  %0 = ptrtoint ptr %p to i64
16  %1 = add i64 %0, %x1
17  %2 = inttoptr i64 %1 to ptr
18  %data = load i32, ptr %2
19  %3 = icmp eq i32 %data, 0
20  br i1 %3, label %latch, label %false
21
22false:
23  %count2 = add i32 %count1, 1
24  br label %latch
25
26latch:
27  %count4 = phi i32 [%count2, %false], [%count1, %header]
28  %x2 = add i64 %x1, 1
29  %4 = icmp eq i64 %x2, 100
30  br i1 %4, label %exit, label %header
31
32exit:
33  ret i32 %count4
34}
35
36; The block latch and one of false/true should be moved before header.
37;CHECK-LABEL: test2:
38;CHECK:       %true
39;CHECK:       %latch
40;CHECK:       %header
41;CHECK:       %false
42define i32 @test2(ptr %p) {
43entry:
44  br label %header
45
46header:
47  %x1 = phi i64 [0, %entry], [%x2, %latch]
48  %count1 = phi i32 [0, %entry], [%count4, %latch]
49  %0 = ptrtoint ptr %p to i64
50  %1 = add i64 %0, %x1
51  %2 = inttoptr i64 %1 to ptr
52  %data = load i32, ptr %2
53  %3 = icmp eq i32 %data, 0
54  br i1 %3, label %true, label %false
55
56false:
57  %count2 = add i32 %count1, 1
58  br label %latch
59
60true:
61  %count3 = add i32 %count1, 2
62  br label %latch
63
64latch:
65  %count4 = phi i32 [%count2, %false], [%count3, %true]
66  %x2 = add i64 %x1, 1
67  %4 = icmp eq i64 %x2, 100
68  br i1 %4, label %exit, label %header
69
70exit:
71  ret i32 %count4
72}
73
74; More blocks can be moved before header.
75;            header <------------
76;              /\               |
77;             /  \              |
78;            /    \             |
79;           /      \            |
80;          /        \           |
81;        true      false        |
82;         /\         /\         |
83;        /  \       /  \        |
84;       /    \     /    \       |
85;    true3 false3 /      \      |
86;      \    /   true2  false2   |
87;       \  /      \      /      |
88;        \/        \    /       |
89;      endif3       \  /        |
90;         \          \/         |
91;          \       endif2       |
92;           \        /          |
93;            \      /           |
94;             \    /            |
95;              \  /             |
96;               \/              |
97;              latch-------------
98;                |
99;                |
100;              exit
101;
102; Blocks true3,endif3,latch should be moved before header.
103;
104;CHECK-LABEL: test3:
105;CHECK:       %true3
106;CHECK:       %endif3
107;CHECK:       %latch
108;CHECK:       %header
109;CHECK:       %false
110define i32 @test3(ptr %p) {
111entry:
112  br label %header
113
114header:
115  %x1 = phi i64 [0, %entry], [%x2, %latch]
116  %count1 = phi i32 [0, %entry], [%count12, %latch]
117  %0 = ptrtoint ptr %p to i64
118  %1 = add i64 %0, %x1
119  %2 = inttoptr i64 %1 to ptr
120  %data = load i32, ptr %2
121  %3 = icmp eq i32 %data, 0
122  br i1 %3, label %true, label %false, !prof !3
123
124false:
125  %count2 = add i32 %count1, 1
126  %cond = icmp sgt i32 %count2, 10
127  br i1 %cond, label %true2, label %false2
128
129false2:
130  %count3 = and i32 %count2, 7
131  br label %endif2
132
133true2:
134  %count4 = mul i32 %count2, 3
135  br label %endif2
136
137endif2:
138  %count5 = phi i32 [%count3, %false2], [%count4, %true2]
139  %count6 = sub i32 %count5, 5
140  br label %latch
141
142true:
143  %count7 = add i32 %count1, 2
144  %cond2 = icmp slt i32 %count7, 20
145  br i1 %cond2, label %true3, label %false3
146
147false3:
148  %count8 = or i32 %count7, 3
149  br label %endif3
150
151true3:
152  %count9 = xor i32 %count7, 55
153  br label %endif3
154
155endif3:
156  %count10 = phi i32 [%count8, %false3], [%count9, %true3]
157  %count11 = add i32 %count10, 3
158  br label %latch
159
160latch:
161  %count12 = phi i32 [%count6, %endif2], [%count11, %endif3]
162  %x2 = add i64 %x1, 1
163  %4 = icmp eq i64 %x2, 100
164  br i1 %4, label %exit, label %header
165
166exit:
167  ret i32 %count12
168}
169
170; The exit block has higher frequency than false block, so latch block
171; should not moved before header.
172;CHECK-LABEL: test4:
173;CHECK:       %header
174;CHECK:       %true
175;CHECK:       %latch
176;CHECK:       %false
177;CHECK:       %exit
178define i32 @test4(i32 %t, ptr %p) {
179entry:
180  br label %header
181
182header:
183  %x1 = phi i64 [0, %entry], [%x2, %latch]
184  %count1 = phi i32 [0, %entry], [%count4, %latch]
185  %0 = ptrtoint ptr %p to i64
186  %1 = add i64 %0, %x1
187  %2 = inttoptr i64 %1 to ptr
188  %data = load i32, ptr %2
189  %3 = icmp eq i32 %data, 0
190  br i1 %3, label %true, label %false, !prof !1
191
192false:
193  %count2 = add i32 %count1, 1
194  br label %latch
195
196true:
197  %count3 = add i32 %count1, 2
198  br label %latch
199
200latch:
201  %count4 = phi i32 [%count2, %false], [%count3, %true]
202  %x2 = add i64 %x1, 1
203  %4 = icmp eq i64 %x2, 100
204  br i1 %4, label %exit, label %header, !prof !2
205
206exit:
207  ret i32 %count4
208}
209
210!1 = !{!"branch_weights", i32 100, i32 1}
211!2 = !{!"branch_weights", i32 16, i32 16}
212!3 = !{!"branch_weights", i32 51, i32 49}
213
214; If move latch to loop top doesn't reduce taken branch, don't do it.
215;CHECK-LABEL: test5:
216;CHECK:       %entry
217;CHECK:       %header
218;CHECK:       %latch
219define void @test5(ptr %p) {
220entry:
221  br label %header
222
223header:
224  %x1 = phi i64 [0, %entry], [%x1, %header], [%x2, %latch]
225  %0 = ptrtoint ptr %p to i64
226  %1 = add i64 %0, %x1
227  %2 = inttoptr i64 %1 to ptr
228  %data = load i32, ptr %2
229  %3 = icmp eq i32 %data, 0
230  br i1 %3, label %latch, label %header
231
232latch:
233  %x2 = add i64 %x1, 1
234  br label %header
235
236exit:
237  ret void
238}
239
240