xref: /llvm-project/llvm/test/Transforms/GVNSink/cycles.ll (revision 89aeefce4a01e744d8480e8fe4599cbc93f093cb)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -passes=gvn-sink -S %s | FileCheck %s
3
4declare i32 @foo()
5
6define void @loop1() {
7; CHECK-LABEL: define void @loop1() {
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[LOOP:%.*]]
10; CHECK:       loop:
11; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
12; CHECK-NEXT:    br label [[LOOP]]
13;
14entry:
15  %c1 = call i32 @foo()
16  br label %loop
17
18loop:
19  %c2 = call i32 @foo()
20  br label %loop
21}
22
23define void @uncond_succ_no_loop() {
24; CHECK-LABEL: define void @uncond_succ_no_loop() {
25; CHECK-NEXT:  entry:
26; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
27; CHECK-NEXT:    br label [[EXIT:%.*]]
28; CHECK:       exit:
29; CHECK-NEXT:    [[C2:%.*]] = call i32 @foo()
30; CHECK-NEXT:    ret void
31;
32entry:
33  %c1 = call i32 @foo()
34  br label %exit
35
36exit:
37  %c2 = call i32 @foo()
38  ret void
39}
40
41define void @loop_with_store(ptr %a) {
42; CHECK-LABEL: define void @loop_with_store
43; CHECK-SAME: (ptr [[A:%.*]]) {
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
46; CHECK-NEXT:    br label [[LOOP:%.*]]
47; CHECK:       loop:
48; CHECK-NEXT:    [[C2:%.*]] = call i32 @foo()
49; CHECK-NEXT:    store i32 0, ptr [[A]], align 4
50; CHECK-NEXT:    br label [[LOOP]]
51;
52entry:
53  %c1 = call i32 @foo()
54  br label %loop
55
56loop:
57  %c2 = call i32 @foo()
58  store i32 0, ptr %a
59  br label %loop
60}
61
62define void @loop_linked_latches() {
63; CHECK-LABEL: define void @loop_linked_latches() {
64; CHECK-NEXT:  entry:
65; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
66; CHECK-NEXT:    br label [[LOOP:%.*]]
67; CHECK:       loop:
68; CHECK-NEXT:    [[C2:%.*]] = call i32 @foo()
69; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[C2]], 100
70; CHECK-NEXT:    br i1 [[C]], label [[LATCH_1:%.*]], label [[EXIT:%.*]]
71; CHECK:       latch.1:
72; CHECK-NEXT:    br label [[LATCH_2:%.*]]
73; CHECK:       latch.2:
74; CHECK-NEXT:    br label [[LOOP]]
75; CHECK:       exit:
76; CHECK-NEXT:    ret void
77;
78entry:
79  %c1 = call i32 @foo()
80  br label %loop
81
82loop:
83  %c2  = call i32 @foo()
84  %c = icmp eq i32 %c2, 100
85  br i1 %c, label %latch.1, label %exit
86
87latch.1:
88  br label %latch.2
89
90latch.2:
91  br label %loop
92
93
94exit:
95  ret void
96}
97
98define void @loop_with_branch(i32 %s) {
99; CHECK-LABEL: define void @loop_with_branch
100; CHECK-SAME: (i32 [[S:%.*]]) {
101; CHECK-NEXT:  entry:
102; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
103; CHECK:       loop.header:
104; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
105; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[S]], 100
106; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]]
107; CHECK:       loop.latch:
108; CHECK-NEXT:    br label [[LOOP_HEADER]]
109; CHECK:       exit:
110; CHECK-NEXT:    ret void
111;
112entry:
113  %c1 = call i32 @foo()
114  br label %loop.header
115
116loop.header:
117  %cmp = icmp eq i32 %s, 100
118  br i1 %cmp, label %loop.latch, label %exit
119
120loop.latch:
121  %c2 = call i32 @foo()
122  br label %loop.header
123
124exit:
125  ret void
126}
127
128define void @loop_with_switch(i32 %s) {
129; CHECK-LABEL: define void @loop_with_switch
130; CHECK-SAME: (i32 [[S:%.*]]) {
131; CHECK-NEXT:  entry:
132; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
133; CHECK:       loop.header:
134; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
135; CHECK-NEXT:    switch i32 [[S]], label [[LOOP_LATCH:%.*]] [
136; CHECK-NEXT:    i32 0, label [[EXIT:%.*]]
137; CHECK-NEXT:    ]
138; CHECK:       loop.latch:
139; CHECK-NEXT:    br label [[LOOP_HEADER]]
140; CHECK:       exit:
141; CHECK-NEXT:    ret void
142;
143entry:
144  %c1 = call i32 @foo()
145  br label %loop.header
146
147loop.header:
148  switch i32 %s, label %loop.latch [
149  i32 0, label %exit
150  ]
151
152loop.latch:
153  %c2 = call i32 @foo()
154  br label %loop.header
155
156exit:
157  ret void
158}
159
160define void @cycle_latch_not_dominated_by_header_branch(i1 %c, i32 %s) {
161; CHECK-LABEL: define void @cycle_latch_not_dominated_by_header_branch
162; CHECK-SAME: (i1 [[C:%.*]], i32 [[S:%.*]]) {
163; CHECK-NEXT:  entry:
164; CHECK-NEXT:    br i1 [[C]], label [[THEN:%.*]], label [[CYCLE_2:%.*]]
165; CHECK:       then:
166; CHECK-NEXT:    br label [[CYCLE_1:%.*]]
167; CHECK:       cycle.1:
168; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
169; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[S]], 100
170; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[CYCLE_2]]
171; CHECK:       cycle.2:
172; CHECK-NEXT:    br label [[CYCLE_1]]
173; CHECK:       exit:
174; CHECK-NEXT:    ret void
175;
176entry:
177  br i1 %c, label %then, label %cycle.2
178
179then:
180  %c1 = call i32 @foo()
181  br label %cycle.1
182
183cycle.1:
184  %cmp = icmp eq i32 %s, 100
185  br i1 %cmp, label %exit, label %cycle.2
186
187cycle.2:
188  %c2 = call i32 @foo()
189  br label %cycle.1
190
191exit:
192  ret void
193}
194
195define void @cycle_latch_not_dominated_by_header_switch(i1 %c, i32 %s) {
196; CHECK-LABEL: define void @cycle_latch_not_dominated_by_header_switch
197; CHECK-SAME: (i1 [[C:%.*]], i32 [[S:%.*]]) {
198; CHECK-NEXT:  entry:
199; CHECK-NEXT:    br i1 [[C]], label [[THEN:%.*]], label [[CYCLE_2:%.*]]
200; CHECK:       then:
201; CHECK-NEXT:    br label [[CYCLE_1:%.*]]
202; CHECK:       cycle.1:
203; CHECK-NEXT:    [[C1:%.*]] = call i32 @foo()
204; CHECK-NEXT:    switch i32 [[S]], label [[EXIT:%.*]] [
205; CHECK-NEXT:    i32 0, label [[CYCLE_2]]
206; CHECK-NEXT:    ]
207; CHECK:       cycle.2:
208; CHECK-NEXT:    br label [[CYCLE_1]]
209; CHECK:       exit:
210; CHECK-NEXT:    ret void
211;
212entry:
213  br i1 %c, label %then, label %cycle.2
214
215then:
216  %c1 = call i32 @foo()
217  br label %cycle.1
218
219cycle.1:
220  switch i32 %s, label %exit [
221  i32 0, label %cycle.2
222  ]
223
224cycle.2:
225  %c2 = call i32 @foo()
226  br label %cycle.1
227
228exit:
229  ret void
230}
231
232