1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -loop-reduce -S | FileCheck %s
3; REQUIRES: x86-registered-target
4
5target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
6target triple = "x86_64-unknown-linux-gnu"
7
8; FIXME: iv.next is supposed to be inserted in the backedge.
9define i32 @test_01(i32* %p, i64 %len, i32 %x) {
10; CHECK-LABEL: @test_01(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
13; CHECK-NEXT:    br label [[LOOP:%.*]]
14; CHECK:       loop:
15; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
16; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
17; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
18; CHECK:       backedge:
19; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[IV]]
20; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
21; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
22; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], -1
23; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
24; CHECK:       exit:
25; CHECK-NEXT:    ret i32 -1
26; CHECK:       failure:
27; CHECK-NEXT:    unreachable
28;
29entry:
30  br label %loop
31
32loop:                                             ; preds = %backedge, %entry
33  %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
34  %iv.next = add nsw i64 %iv, -1
35  %cond_1 = icmp eq i64 %iv, 0
36  br i1 %cond_1, label %exit, label %backedge
37
38backedge:                                         ; preds = %loop
39  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next
40  %loaded = load atomic i32, i32* %addr unordered, align 4
41  %cond_2 = icmp eq i32 %loaded, %x
42  br i1 %cond_2, label %failure, label %loop
43
44exit:                                             ; preds = %loop
45  ret i32 -1
46
47failure:                                          ; preds = %backedge
48  unreachable
49}
50
51define i32 @test_02(i32* %p, i64 %len, i32 %x) {
52; CHECK-LABEL: @test_02(
53; CHECK-NEXT:  entry:
54; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
55; CHECK-NEXT:    br label [[LOOP:%.*]]
56; CHECK:       loop:
57; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
58; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[LSR_IV]], 0
59; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
60; CHECK:       backedge:
61; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[LSR_IV]]
62; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
63; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
64; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
65; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
66; CHECK:       exit:
67; CHECK-NEXT:    ret i32 -1
68; CHECK:       failure:
69; CHECK-NEXT:    unreachable
70;
71entry:
72  %start = add i64 %len, -1
73  br label %loop
74
75loop:                                             ; preds = %backedge, %entry
76  %iv = phi i64 [ %iv.next, %backedge ], [ %start, %entry ]
77  %iv.next = add nsw i64 %iv, -1
78  %iv.offset = add i64 %iv, 1
79  %iv.next.offset = add i64 %iv.next, 1
80  %cond_1 = icmp eq i64 %iv.offset, 0
81  br i1 %cond_1, label %exit, label %backedge
82
83backedge:                                         ; preds = %loop
84  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next.offset
85  %loaded = load atomic i32, i32* %addr unordered, align 4
86  %cond_2 = icmp eq i32 %loaded, %x
87  br i1 %cond_2, label %failure, label %loop
88
89exit:                                             ; preds = %loop
90  ret i32 -1
91
92failure:                                          ; preds = %backedge
93  unreachable
94}
95
96define i32 @test_03(i32* %p, i64 %len, i32 %x) {
97; CHECK-LABEL: @test_03(
98; CHECK-NEXT:  entry:
99; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
100; CHECK-NEXT:    br label [[LOOP:%.*]]
101; CHECK:       loop:
102; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
103; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[LSR_IV]], 0
104; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
105; CHECK:       backedge:
106; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[LSR_IV]]
107; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
108; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
109; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
110; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
111; CHECK:       exit:
112; CHECK-NEXT:    ret i32 -1
113; CHECK:       failure:
114; CHECK-NEXT:    unreachable
115;
116entry:
117  %start = add i64 %len, -100
118  br label %loop
119
120loop:                                             ; preds = %backedge, %entry
121  %iv = phi i64 [ %iv.next, %backedge ], [ %start, %entry ]
122  %iv.next = add nsw i64 %iv, -1
123  %iv.offset = add i64 %iv, 100
124  %iv.next.offset = add i64 %iv.next, 100
125  %cond_1 = icmp eq i64 %iv.offset, 0
126  br i1 %cond_1, label %exit, label %backedge
127
128backedge:                                         ; preds = %loop
129  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next.offset
130  %loaded = load atomic i32, i32* %addr unordered, align 4
131  %cond_2 = icmp eq i32 %loaded, %x
132  br i1 %cond_2, label %failure, label %loop
133
134exit:                                             ; preds = %loop
135  ret i32 -1
136
137failure:                                          ; preds = %backedge
138  unreachable
139}
140
141define i32 @test_04(i32* %p, i64 %len, i32 %x) {
142; CHECK-LABEL: @test_04(
143; CHECK-NEXT:  entry:
144; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
145; CHECK-NEXT:    br label [[LOOP:%.*]]
146; CHECK:       loop:
147; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
148; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
149; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
150; CHECK:       backedge:
151; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[IV]]
152; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
153; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
154; CHECK-NEXT:    [[IV_NEXT]] = sub i64 [[IV]], 1
155; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
156; CHECK:       exit:
157; CHECK-NEXT:    ret i32 -1
158; CHECK:       failure:
159; CHECK-NEXT:    unreachable
160;
161entry:
162  br label %loop
163
164loop:                                             ; preds = %backedge, %entry
165  %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
166  %iv.next = sub i64 %iv, 1
167  %cond_1 = icmp eq i64 %iv, 0
168  br i1 %cond_1, label %exit, label %backedge
169
170backedge:                                         ; preds = %loop
171  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next
172  %loaded = load atomic i32, i32* %addr unordered, align 4
173  %cond_2 = icmp eq i32 %loaded, %x
174  br i1 %cond_2, label %failure, label %loop
175
176exit:                                             ; preds = %loop
177  ret i32 -1
178
179failure:                                          ; preds = %backedge
180  unreachable
181}
182
183define i32 @test_05(i32* %p, i64 %len, i32 %x) {
184; CHECK-LABEL: @test_05(
185; CHECK-NEXT:  entry:
186; CHECK-NEXT:    br label [[LOOP:%.*]]
187; CHECK:       loop:
188; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
189; CHECK-NEXT:    [[IV_NEXT]] = mul i64 [[IV]], 2
190; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
191; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
192; CHECK:       backedge:
193; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[IV_NEXT]]
194; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[ADDR]] unordered, align 4
195; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
196; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
197; CHECK:       exit:
198; CHECK-NEXT:    ret i32 -1
199; CHECK:       failure:
200; CHECK-NEXT:    unreachable
201;
202entry:
203  br label %loop
204
205loop:                                             ; preds = %backedge, %entry
206  %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
207  %iv.next = mul i64 %iv, 2
208  %cond_1 = icmp eq i64 %iv, 0
209  br i1 %cond_1, label %exit, label %backedge
210
211backedge:                                         ; preds = %loop
212  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next
213  %loaded = load atomic i32, i32* %addr unordered, align 4
214  %cond_2 = icmp eq i32 %loaded, %x
215  br i1 %cond_2, label %failure, label %loop
216
217exit:                                             ; preds = %loop
218  ret i32 -1
219
220failure:                                          ; preds = %backedge
221  unreachable
222}
223
224define i32 @test_06(i32* %p, i64 %len, i32 %x, i64 %step) {
225; CHECK-LABEL: @test_06(
226; CHECK-NEXT:  entry:
227; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[STEP:%.*]]
228; CHECK-NEXT:    br label [[LOOP:%.*]]
229; CHECK:       loop:
230; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
231; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], [[STEP]]
232; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[STEP]], [[IV_NEXT]]
233; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
234; CHECK:       backedge:
235; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[IV]]
236; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
237; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
238; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
239; CHECK:       exit:
240; CHECK-NEXT:    ret i32 -1
241; CHECK:       failure:
242; CHECK-NEXT:    unreachable
243;
244entry:
245  br label %loop
246
247loop:                                             ; preds = %backedge, %entry
248  %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
249  %iv.next = add nsw i64 %iv, %step
250  %cond_1 = icmp eq i64 %iv, 0
251  br i1 %cond_1, label %exit, label %backedge
252
253backedge:                                         ; preds = %loop
254  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next
255  %loaded = load atomic i32, i32* %addr unordered, align 4
256  %cond_2 = icmp eq i32 %loaded, %x
257  br i1 %cond_2, label %failure, label %loop
258
259exit:                                             ; preds = %loop
260  ret i32 -1
261
262failure:                                          ; preds = %backedge
263  unreachable
264}
265