1; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s | FileCheck %s
2
3define void @test_chained_first_order_recurrences_1(i16* %ptr) {
4; CHECK-LABEL: @test_chained_first_order_recurrences_1
5; CHECK-NOT: vector.body:
6;
7entry:
8  br label %loop
9
10loop:
11  %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
12  %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
13  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
14  %iv.next = add nuw nsw i64 %iv, 1
15  %gep.ptr = getelementptr inbounds i16, i16* %ptr, i64 %iv
16  %for.1.next = load i16, i16* %gep.ptr, align 2
17  %add = add i16 %for.1, %for.2
18  store i16 %add, i16* %gep.ptr
19  %exitcond.not = icmp eq i64 %iv.next, 1000
20  br i1 %exitcond.not, label %exit, label %loop
21
22exit:
23  ret void
24}
25
26define void @test_chained_first_order_recurrences_2(i16* %ptr) {
27; CHECK-LABEL: @test_chained_first_order_recurrences_2
28; CHECK-NOT: vector.body:
29;
30entry:
31  br label %loop
32
33loop:
34  %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
35  %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
36  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
37  %iv.next = add nuw nsw i64 %iv, 1
38  %gep.ptr = getelementptr inbounds i16, i16* %ptr, i64 %iv
39  %for.1.next = load i16, i16* %gep.ptr, align 2
40  %add = add i16 %for.1, %for.2
41  store i16 %add, i16* %gep.ptr
42  %exitcond.not = icmp eq i64 %iv.next, 1000
43  br i1 %exitcond.not, label %exit, label %loop
44
45exit:
46  ret void
47}
48
49define void @test_chained_first_order_recurrences_3(i16* %ptr) {
50; CHECK-LABEL: @test_chained_first_order_recurrences_3
51; CHECK-NOT: vector.body:
52;
53entry:
54  br label %loop
55
56loop:
57  %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
58  %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
59  %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
60  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
61  %iv.next = add nuw nsw i64 %iv, 1
62  %gep.ptr = getelementptr inbounds i16, i16* %ptr, i64 %iv
63  %for.1.next = load i16, i16* %gep.ptr, align 2
64  %add.1 = add i16 %for.1, %for.2
65  %add.2 = add i16 %add.1, %for.3
66  store i16 %add.2, i16* %gep.ptr
67  %exitcond.not = icmp eq i64 %iv.next, 1000
68  br i1 %exitcond.not, label %exit, label %loop
69
70exit:
71  ret void
72}
73
74
75define void @test_cyclic_phis(i16* %ptr) {
76; CHECK-LABEL: @test_cyclic_phis
77; CHECK-NOT: vector.body:
78;
79entry:
80  br label %loop
81
82loop:
83  %for.1 = phi i16 [ 22, %entry ], [ %for.2, %loop ]
84  %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
85  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
86  %iv.next = add nuw nsw i64 %iv, 1
87  %gep.ptr = getelementptr inbounds i16, i16* %ptr, i64 %iv
88  %for.1.next = load i16, i16* %gep.ptr, align 2
89  %add = add i16 %for.1, %for.2
90  store i16 %add, i16* %gep.ptr
91  %exitcond.not = icmp eq i64 %iv.next, 1000
92  br i1 %exitcond.not, label %exit, label %loop
93
94exit:
95  ret void
96}
97
98define void @test_first_order_recurrences_incoming_cycle_preheader(i16* %ptr) {
99; CHECK-LABEL: @test_first_order_recurrences_incoming_cycle_preheader
100; CHECK:       vector.body:
101; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
102; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 0>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
103; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
104; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, i16* [[PTR:%.*]], i64 [[TMP0]]
105; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, i16* [[TMP1]], i32 0
106; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i16* [[TMP2]] to <4 x i16>*
107; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, <4 x i16>* [[TMP3]], align 2
108; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
109; CHECK-NEXT:    [[TMP5:%.*]] = add <4 x i16> [[TMP4]], <i16 10, i16 10, i16 10, i16 10>
110; CHECK-NEXT:    [[TMP6:%.*]] = bitcast i16* [[TMP2]] to <4 x i16>*
111; CHECK-NEXT:    store <4 x i16> [[TMP5]], <4 x i16>* [[TMP6]], align 2
112; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
113; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
114; CHECK-NEXT:    br i1 [[TMP7]], label %middle.block, label %vector.body
115;
116entry:
117  br label %loop.1
118
119loop.1:
120  %p = phi i16 [ 0, %entry ], [ %p, %loop.1 ]
121  br i1 true, label %loop, label %loop.1
122
123loop:
124  %for.1 = phi i16 [ %p, %loop.1 ], [ %for.1.next, %loop ]
125  %iv = phi i64 [ 0, %loop.1 ], [ %iv.next, %loop ]
126  %iv.next = add nuw nsw i64 %iv, 1
127  %gep.ptr = getelementptr inbounds i16, i16* %ptr, i64 %iv
128  %for.1.next = load i16, i16* %gep.ptr, align 2
129  %add = add i16 %for.1, 10
130  store i16 %add, i16* %gep.ptr
131  %exitcond.not = icmp eq i64 %iv.next, 1000
132  br i1 %exitcond.not, label %exit, label %loop
133
134exit:
135  ret void
136}
137
138define void @test_chained_first_order_recurrence_sink_users_1(double* %ptr) {
139; CHECK-LABEL: @test_chained_first_order_recurrence_sink_users_1
140; CHECK-NOT: vector.body:
141;
142entry:
143  br label %loop
144
145loop:
146  %for.1 = phi double [ 10.0, %entry ], [ %for.1.next, %loop ]
147  %for.2 = phi double [ 20.0, %entry ], [ %for.1, %loop ]
148  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
149  %add.1 = fadd double 10.0, %for.2
150  %add.2 = fadd double %add.1, %for.1
151  %iv.next = add nuw nsw i64 %iv, 1
152  %gep.ptr = getelementptr inbounds double, double* %ptr, i64 %iv
153  %for.1.next  = load double, double* %gep.ptr, align 8
154  store double %add.2, double* %gep.ptr
155  %exitcond.not = icmp eq i64 %iv.next, 1000
156  br i1 %exitcond.not, label %exit, label %loop
157
158exit:
159  ret void
160}
161