Vectorizer: Add support for loop reductions.
[oota-llvm.git] / test / Transforms / LoopVectorize / reduction.ll
1 ; RUN: opt < %s  -loop-vectorize -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_bad
97 ;CHECK-NOT: <4 x i32>
98 ;CHECK: ret i32
99 define i32 @reduction_bad(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 ], [ 0, %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 }