Add support for additional reduction variables: AND, OR, XOR.
[oota-llvm.git] / test / Transforms / LoopVectorize / reduction.ll
1 ; RUN: opt < %s  -loop-vectorize -force-vector-width=4 -dce -instcombine -licm -S | FileCheck %s
2
3 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
4 target triple = "x86_64-apple-macosx10.8.0"
5
6 ;CHECK: @reduction_sum
7 ;CHECK: phi <4 x i32>
8 ;CHECK: load <4 x i32>
9 ;CHECK: add <4 x i32>
10 ;CHECK: ret i32
11 define i32 @reduction_sum(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
12   %1 = icmp sgt i32 %n, 0
13   br i1 %1, label %.lr.ph, label %._crit_edge
14
15 .lr.ph:                                           ; preds = %0, %.lr.ph
16   %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
17   %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ]
18   %2 = getelementptr inbounds i32* %A, i64 %indvars.iv
19   %3 = load i32* %2, align 4
20   %4 = getelementptr inbounds i32* %B, i64 %indvars.iv
21   %5 = load i32* %4, align 4
22   %6 = trunc i64 %indvars.iv to i32
23   %7 = add i32 %sum.02, %6
24   %8 = add i32 %7, %3
25   %9 = add i32 %8, %5
26   %indvars.iv.next = add i64 %indvars.iv, 1
27   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
28   %exitcond = icmp eq i32 %lftr.wideiv, %n
29   br i1 %exitcond, label %._crit_edge, label %.lr.ph
30
31 ._crit_edge:                                      ; preds = %.lr.ph, %0
32   %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ]
33   ret i32 %sum.0.lcssa
34 }
35
36 ;CHECK: @reduction_prod
37 ;CHECK: phi <4 x i32>
38 ;CHECK: load <4 x i32>
39 ;CHECK: mul <4 x i32>
40 ;CHECK: ret i32
41 define i32 @reduction_prod(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
42   %1 = icmp sgt i32 %n, 0
43   br i1 %1, label %.lr.ph, label %._crit_edge
44
45 .lr.ph:                                           ; preds = %0, %.lr.ph
46   %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
47   %prod.02 = phi i32 [ %9, %.lr.ph ], [ 1, %0 ]
48   %2 = getelementptr inbounds i32* %A, i64 %indvars.iv
49   %3 = load i32* %2, align 4
50   %4 = getelementptr inbounds i32* %B, i64 %indvars.iv
51   %5 = load i32* %4, align 4
52   %6 = trunc i64 %indvars.iv to i32
53   %7 = mul i32 %prod.02, %6
54   %8 = mul i32 %7, %3
55   %9 = mul i32 %8, %5
56   %indvars.iv.next = add i64 %indvars.iv, 1
57   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
58   %exitcond = icmp eq i32 %lftr.wideiv, %n
59   br i1 %exitcond, label %._crit_edge, label %.lr.ph
60
61 ._crit_edge:                                      ; preds = %.lr.ph, %0
62   %prod.0.lcssa = phi i32 [ 1, %0 ], [ %9, %.lr.ph ]
63   ret i32 %prod.0.lcssa
64 }
65
66 ;CHECK: @reduction_mix
67 ;CHECK: phi <4 x i32>
68 ;CHECK: load <4 x i32>
69 ;CHECK: mul <4 x i32>
70 ;CHECK: ret i32
71 define i32 @reduction_mix(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
72   %1 = icmp sgt i32 %n, 0
73   br i1 %1, label %.lr.ph, label %._crit_edge
74
75 .lr.ph:                                           ; preds = %0, %.lr.ph
76   %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
77   %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ]
78   %2 = getelementptr inbounds i32* %A, i64 %indvars.iv
79   %3 = load i32* %2, align 4
80   %4 = getelementptr inbounds i32* %B, i64 %indvars.iv
81   %5 = load i32* %4, align 4
82   %6 = mul nsw i32 %5, %3
83   %7 = trunc i64 %indvars.iv to i32
84   %8 = add i32 %sum.02, %7
85   %9 = add i32 %8, %6
86   %indvars.iv.next = add i64 %indvars.iv, 1
87   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
88   %exitcond = icmp eq i32 %lftr.wideiv, %n
89   br i1 %exitcond, label %._crit_edge, label %.lr.ph
90
91 ._crit_edge:                                      ; preds = %.lr.ph, %0
92   %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ]
93   ret i32 %sum.0.lcssa
94 }
95
96 ;CHECK: @reduction_mul
97 ;CHECK: mul <4 x i32>
98 ;CHECK: ret i32
99 define i32 @reduction_mul(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp {
100   %1 = icmp sgt i32 %n, 0
101   br i1 %1, label %.lr.ph, label %._crit_edge
102
103 .lr.ph:                                           ; preds = %0, %.lr.ph
104   %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
105   %sum.02 = phi i32 [ %9, %.lr.ph ], [ 19, %0 ]
106   %2 = getelementptr inbounds i32* %A, i64 %indvars.iv
107   %3 = load i32* %2, align 4
108   %4 = getelementptr inbounds i32* %B, i64 %indvars.iv
109   %5 = load i32* %4, align 4
110   %6 = trunc i64 %indvars.iv to i32
111   %7 = add i32 %3, %6
112   %8 = add i32 %7, %5
113   %9 = mul i32 %8, %sum.02
114   %indvars.iv.next = add i64 %indvars.iv, 1
115   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
116   %exitcond = icmp eq i32 %lftr.wideiv, %n
117   br i1 %exitcond, label %._crit_edge, label %.lr.ph
118
119 ._crit_edge:                                      ; preds = %.lr.ph, %0
120   %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ]
121   ret i32 %sum.0.lcssa
122 }
123
124 ;CHECK: @start_at_non_zero
125 ;CHECK: phi <4 x i32>
126 ;CHECK: <i32 120, i32 0, i32 0, i32 0>
127 ;CHECK: ret i32
128 define i32 @start_at_non_zero(i32* nocapture %in, i32* nocapture %coeff, i32* nocapture %out, i32 %n) nounwind uwtable readonly ssp {
129 entry:
130   %cmp7 = icmp sgt i32 %n, 0
131   br i1 %cmp7, label %for.body, label %for.end
132
133 for.body:                                         ; preds = %entry, %for.body
134   %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
135   %sum.09 = phi i32 [ %add, %for.body ], [ 120, %entry ]
136   %arrayidx = getelementptr inbounds i32* %in, i64 %indvars.iv
137   %0 = load i32* %arrayidx, align 4
138   %arrayidx2 = getelementptr inbounds i32* %coeff, i64 %indvars.iv
139   %1 = load i32* %arrayidx2, align 4
140   %mul = mul nsw i32 %1, %0
141   %add = add nsw i32 %mul, %sum.09
142   %indvars.iv.next = add i64 %indvars.iv, 1
143   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
144   %exitcond = icmp eq i32 %lftr.wideiv, %n
145   br i1 %exitcond, label %for.end, label %for.body
146
147 for.end:                                          ; preds = %for.body, %entry
148   %sum.0.lcssa = phi i32 [ 120, %entry ], [ %add, %for.body ]
149   ret i32 %sum.0.lcssa
150 }
151
152 ;CHECK: @reduction_and
153 ;CHECK: and <4 x i32>
154 ;CHECK: ret i32
155 define i32 @reduction_and(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly {
156 entry:
157   %cmp7 = icmp sgt i32 %n, 0
158   br i1 %cmp7, label %for.body, label %for.end
159
160 for.body:                                         ; preds = %entry, %for.body
161   %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
162   %result.08 = phi i32 [ %and, %for.body ], [ -1, %entry ]
163   %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
164   %0 = load i32* %arrayidx, align 4
165   %arrayidx2 = getelementptr inbounds i32* %B, i64 %indvars.iv
166   %1 = load i32* %arrayidx2, align 4
167   %add = add nsw i32 %1, %0
168   %and = and i32 %add, %result.08
169   %indvars.iv.next = add i64 %indvars.iv, 1
170   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
171   %exitcond = icmp eq i32 %lftr.wideiv, %n
172   br i1 %exitcond, label %for.end, label %for.body
173
174 for.end:                                          ; preds = %for.body, %entry
175   %result.0.lcssa = phi i32 [ -1, %entry ], [ %and, %for.body ]
176   ret i32 %result.0.lcssa
177 }
178
179 ;CHECK: @reduction_or
180 ;CHECK: or <4 x i32>
181 ;CHECK: ret i32
182 define i32 @reduction_or(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly {
183 entry:
184   %cmp7 = icmp sgt i32 %n, 0
185   br i1 %cmp7, label %for.body, label %for.end
186
187 for.body:                                         ; preds = %entry, %for.body
188   %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
189   %result.08 = phi i32 [ %or, %for.body ], [ 0, %entry ]
190   %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
191   %0 = load i32* %arrayidx, align 4
192   %arrayidx2 = getelementptr inbounds i32* %B, i64 %indvars.iv
193   %1 = load i32* %arrayidx2, align 4
194   %add = add nsw i32 %1, %0
195   %or = or i32 %add, %result.08
196   %indvars.iv.next = add i64 %indvars.iv, 1
197   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
198   %exitcond = icmp eq i32 %lftr.wideiv, %n
199   br i1 %exitcond, label %for.end, label %for.body
200
201 for.end:                                          ; preds = %for.body, %entry
202   %result.0.lcssa = phi i32 [ 0, %entry ], [ %or, %for.body ]
203   ret i32 %result.0.lcssa
204 }
205
206 ;CHECK: @reduction_xor
207 ;CHECK: xor <4 x i32>
208 ;CHECK: ret i32
209 define i32 @reduction_xor(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly {
210 entry:
211   %cmp7 = icmp sgt i32 %n, 0
212   br i1 %cmp7, label %for.body, label %for.end
213
214 for.body:                                         ; preds = %entry, %for.body
215   %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
216   %result.08 = phi i32 [ %xor, %for.body ], [ 0, %entry ]
217   %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
218   %0 = load i32* %arrayidx, align 4
219   %arrayidx2 = getelementptr inbounds i32* %B, i64 %indvars.iv
220   %1 = load i32* %arrayidx2, align 4
221   %add = add nsw i32 %1, %0
222   %xor = xor i32 %add, %result.08
223   %indvars.iv.next = add i64 %indvars.iv, 1
224   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
225   %exitcond = icmp eq i32 %lftr.wideiv, %n
226   br i1 %exitcond, label %for.end, label %for.body
227
228 for.end:                                          ; preds = %for.body, %entry
229   %result.0.lcssa = phi i32 [ 0, %entry ], [ %xor, %for.body ]
230   ret i32 %result.0.lcssa
231 }