[ARM] Adjust how NEON shifts are lowered
[llvm-core.git] / test / Transforms / SLPVectorizer / X86 / tiny-tree.ll
blob19f06805ff50e6dd5eb1487bdf977a3348052e76
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 | FileCheck %s
4 define void @tiny_tree_fully_vectorizable(double* noalias nocapture %dst, double* noalias nocapture readonly %src, i64 %count) #0 {
5 ; CHECK-LABEL: @tiny_tree_fully_vectorizable(
6 ; CHECK-NEXT:  entry:
7 ; CHECK-NEXT:    [[CMP12:%.*]] = icmp eq i64 [[COUNT:%.*]], 0
8 ; CHECK-NEXT:    br i1 [[CMP12]], label [[FOR_END:%.*]], label [[FOR_BODY:%.*]]
9 ; CHECK:       for.body:
10 ; CHECK-NEXT:    [[I_015:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
11 ; CHECK-NEXT:    [[DST_ADDR_014:%.*]] = phi double* [ [[ADD_PTR4:%.*]], [[FOR_BODY]] ], [ [[DST:%.*]], [[ENTRY]] ]
12 ; CHECK-NEXT:    [[SRC_ADDR_013:%.*]] = phi double* [ [[ADD_PTR:%.*]], [[FOR_BODY]] ], [ [[SRC:%.*]], [[ENTRY]] ]
13 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[SRC_ADDR_013]], i64 1
14 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[SRC_ADDR_013]] to <2 x double>*
15 ; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 8
16 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[DST_ADDR_014]], i64 1
17 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast double* [[DST_ADDR_014]] to <2 x double>*
18 ; CHECK-NEXT:    store <2 x double> [[TMP1]], <2 x double>* [[TMP2]], align 8
19 ; CHECK-NEXT:    [[ADD_PTR]] = getelementptr inbounds double, double* [[SRC_ADDR_013]], i64 [[I_015]]
20 ; CHECK-NEXT:    [[ADD_PTR4]] = getelementptr inbounds double, double* [[DST_ADDR_014]], i64 [[I_015]]
21 ; CHECK-NEXT:    [[INC]] = add i64 [[I_015]], 1
22 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[COUNT]]
23 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]]
24 ; CHECK:       for.end:
25 ; CHECK-NEXT:    ret void
27 entry:
28   %cmp12 = icmp eq i64 %count, 0
29   br i1 %cmp12, label %for.end, label %for.body
31 for.body:                                         ; preds = %entry, %for.body
32   %i.015 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
33   %dst.addr.014 = phi double* [ %add.ptr4, %for.body ], [ %dst, %entry ]
34   %src.addr.013 = phi double* [ %add.ptr, %for.body ], [ %src, %entry ]
35   %0 = load double, double* %src.addr.013, align 8
36   store double %0, double* %dst.addr.014, align 8
37   %arrayidx2 = getelementptr inbounds double, double* %src.addr.013, i64 1
38   %1 = load double, double* %arrayidx2, align 8
39   %arrayidx3 = getelementptr inbounds double, double* %dst.addr.014, i64 1
40   store double %1, double* %arrayidx3, align 8
41   %add.ptr = getelementptr inbounds double, double* %src.addr.013, i64 %i.015
42   %add.ptr4 = getelementptr inbounds double, double* %dst.addr.014, i64 %i.015
43   %inc = add i64 %i.015, 1
44   %exitcond = icmp eq i64 %inc, %count
45   br i1 %exitcond, label %for.end, label %for.body
47 for.end:                                          ; preds = %for.body, %entry
48   ret void
51 define void @tiny_tree_fully_vectorizable2(float* noalias nocapture %dst, float* noalias nocapture readonly %src, i64 %count) #0 {
52 ; CHECK-LABEL: @tiny_tree_fully_vectorizable2(
53 ; CHECK-NEXT:  entry:
54 ; CHECK-NEXT:    [[CMP20:%.*]] = icmp eq i64 [[COUNT:%.*]], 0
55 ; CHECK-NEXT:    br i1 [[CMP20]], label [[FOR_END:%.*]], label [[FOR_BODY:%.*]]
56 ; CHECK:       for.body:
57 ; CHECK-NEXT:    [[I_023:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
58 ; CHECK-NEXT:    [[DST_ADDR_022:%.*]] = phi float* [ [[ADD_PTR8:%.*]], [[FOR_BODY]] ], [ [[DST:%.*]], [[ENTRY]] ]
59 ; CHECK-NEXT:    [[SRC_ADDR_021:%.*]] = phi float* [ [[ADD_PTR:%.*]], [[FOR_BODY]] ], [ [[SRC:%.*]], [[ENTRY]] ]
60 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 1
61 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 1
62 ; CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 2
63 ; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 2
64 ; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 3
65 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast float* [[SRC_ADDR_021]] to <4 x float>*
66 ; CHECK-NEXT:    [[TMP1:%.*]] = load <4 x float>, <4 x float>* [[TMP0]], align 4
67 ; CHECK-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 3
68 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[DST_ADDR_022]] to <4 x float>*
69 ; CHECK-NEXT:    store <4 x float> [[TMP1]], <4 x float>* [[TMP2]], align 4
70 ; CHECK-NEXT:    [[ADD_PTR]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 [[I_023]]
71 ; CHECK-NEXT:    [[ADD_PTR8]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 [[I_023]]
72 ; CHECK-NEXT:    [[INC]] = add i64 [[I_023]], 1
73 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[COUNT]]
74 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]]
75 ; CHECK:       for.end:
76 ; CHECK-NEXT:    ret void
78 entry:
79   %cmp20 = icmp eq i64 %count, 0
80   br i1 %cmp20, label %for.end, label %for.body
82 for.body:                                         ; preds = %entry, %for.body
83   %i.023 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
84   %dst.addr.022 = phi float* [ %add.ptr8, %for.body ], [ %dst, %entry ]
85   %src.addr.021 = phi float* [ %add.ptr, %for.body ], [ %src, %entry ]
86   %0 = load float, float* %src.addr.021, align 4
87   store float %0, float* %dst.addr.022, align 4
88   %arrayidx2 = getelementptr inbounds float, float* %src.addr.021, i64 1
89   %1 = load float, float* %arrayidx2, align 4
90   %arrayidx3 = getelementptr inbounds float, float* %dst.addr.022, i64 1
91   store float %1, float* %arrayidx3, align 4
92   %arrayidx4 = getelementptr inbounds float, float* %src.addr.021, i64 2
93   %2 = load float, float* %arrayidx4, align 4
94   %arrayidx5 = getelementptr inbounds float, float* %dst.addr.022, i64 2
95   store float %2, float* %arrayidx5, align 4
96   %arrayidx6 = getelementptr inbounds float, float* %src.addr.021, i64 3
97   %3 = load float, float* %arrayidx6, align 4
98   %arrayidx7 = getelementptr inbounds float, float* %dst.addr.022, i64 3
99   store float %3, float* %arrayidx7, align 4
100   %add.ptr = getelementptr inbounds float, float* %src.addr.021, i64 %i.023
101   %add.ptr8 = getelementptr inbounds float, float* %dst.addr.022, i64 %i.023
102   %inc = add i64 %i.023, 1
103   %exitcond = icmp eq i64 %inc, %count
104   br i1 %exitcond, label %for.end, label %for.body
106 for.end:                                          ; preds = %for.body, %entry
107   ret void
110 ; We do not vectorize the tiny tree which is not fully vectorizable.
112 define void @tiny_tree_not_fully_vectorizable(double* noalias nocapture %dst, double* noalias nocapture readonly %src, i64 %count) #0 {
113 ; CHECK-LABEL: @tiny_tree_not_fully_vectorizable(
114 ; CHECK-NEXT:  entry:
115 ; CHECK-NEXT:    [[CMP12:%.*]] = icmp eq i64 [[COUNT:%.*]], 0
116 ; CHECK-NEXT:    br i1 [[CMP12]], label [[FOR_END:%.*]], label [[FOR_BODY:%.*]]
117 ; CHECK:       for.body:
118 ; CHECK-NEXT:    [[I_015:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
119 ; CHECK-NEXT:    [[DST_ADDR_014:%.*]] = phi double* [ [[ADD_PTR4:%.*]], [[FOR_BODY]] ], [ [[DST:%.*]], [[ENTRY]] ]
120 ; CHECK-NEXT:    [[SRC_ADDR_013:%.*]] = phi double* [ [[ADD_PTR:%.*]], [[FOR_BODY]] ], [ [[SRC:%.*]], [[ENTRY]] ]
121 ; CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[SRC_ADDR_013]], align 8
122 ; CHECK-NEXT:    store double [[TMP0]], double* [[DST_ADDR_014]], align 8
123 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[SRC_ADDR_013]], i64 2
124 ; CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[ARRAYIDX2]], align 8
125 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[DST_ADDR_014]], i64 1
126 ; CHECK-NEXT:    store double [[TMP1]], double* [[ARRAYIDX3]], align 8
127 ; CHECK-NEXT:    [[ADD_PTR]] = getelementptr inbounds double, double* [[SRC_ADDR_013]], i64 [[I_015]]
128 ; CHECK-NEXT:    [[ADD_PTR4]] = getelementptr inbounds double, double* [[DST_ADDR_014]], i64 [[I_015]]
129 ; CHECK-NEXT:    [[INC]] = add i64 [[I_015]], 1
130 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[COUNT]]
131 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]]
132 ; CHECK:       for.end:
133 ; CHECK-NEXT:    ret void
135 entry:
136   %cmp12 = icmp eq i64 %count, 0
137   br i1 %cmp12, label %for.end, label %for.body
139 for.body:                                         ; preds = %entry, %for.body
140   %i.015 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
141   %dst.addr.014 = phi double* [ %add.ptr4, %for.body ], [ %dst, %entry ]
142   %src.addr.013 = phi double* [ %add.ptr, %for.body ], [ %src, %entry ]
143   %0 = load double, double* %src.addr.013, align 8
144   store double %0, double* %dst.addr.014, align 8
145   %arrayidx2 = getelementptr inbounds double, double* %src.addr.013, i64 2
146   %1 = load double, double* %arrayidx2, align 8
147   %arrayidx3 = getelementptr inbounds double, double* %dst.addr.014, i64 1
148   store double %1, double* %arrayidx3, align 8
149   %add.ptr = getelementptr inbounds double, double* %src.addr.013, i64 %i.015
150   %add.ptr4 = getelementptr inbounds double, double* %dst.addr.014, i64 %i.015
151   %inc = add i64 %i.015, 1
152   %exitcond = icmp eq i64 %inc, %count
153   br i1 %exitcond, label %for.end, label %for.body
155 for.end:                                          ; preds = %for.body, %entry
156   ret void
159 define void @tiny_tree_not_fully_vectorizable2(float* noalias nocapture %dst, float* noalias nocapture readonly %src, i64 %count) #0 {
160 ; CHECK-LABEL: @tiny_tree_not_fully_vectorizable2(
161 ; CHECK-NEXT:  entry:
162 ; CHECK-NEXT:    [[CMP20:%.*]] = icmp eq i64 [[COUNT:%.*]], 0
163 ; CHECK-NEXT:    br i1 [[CMP20]], label [[FOR_END:%.*]], label [[FOR_BODY:%.*]]
164 ; CHECK:       for.body:
165 ; CHECK-NEXT:    [[I_023:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
166 ; CHECK-NEXT:    [[DST_ADDR_022:%.*]] = phi float* [ [[ADD_PTR8:%.*]], [[FOR_BODY]] ], [ [[DST:%.*]], [[ENTRY]] ]
167 ; CHECK-NEXT:    [[SRC_ADDR_021:%.*]] = phi float* [ [[ADD_PTR:%.*]], [[FOR_BODY]] ], [ [[SRC:%.*]], [[ENTRY]] ]
168 ; CHECK-NEXT:    [[TMP0:%.*]] = load float, float* [[SRC_ADDR_021]], align 4
169 ; CHECK-NEXT:    store float [[TMP0]], float* [[DST_ADDR_022]], align 4
170 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 4
171 ; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[ARRAYIDX2]], align 4
172 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 1
173 ; CHECK-NEXT:    store float [[TMP1]], float* [[ARRAYIDX3]], align 4
174 ; CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 2
175 ; CHECK-NEXT:    [[TMP2:%.*]] = load float, float* [[ARRAYIDX4]], align 4
176 ; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 2
177 ; CHECK-NEXT:    store float [[TMP2]], float* [[ARRAYIDX5]], align 4
178 ; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 3
179 ; CHECK-NEXT:    [[TMP3:%.*]] = load float, float* [[ARRAYIDX6]], align 4
180 ; CHECK-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 3
181 ; CHECK-NEXT:    store float [[TMP3]], float* [[ARRAYIDX7]], align 4
182 ; CHECK-NEXT:    [[ADD_PTR]] = getelementptr inbounds float, float* [[SRC_ADDR_021]], i64 [[I_023]]
183 ; CHECK-NEXT:    [[ADD_PTR8]] = getelementptr inbounds float, float* [[DST_ADDR_022]], i64 [[I_023]]
184 ; CHECK-NEXT:    [[INC]] = add i64 [[I_023]], 1
185 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[COUNT]]
186 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]]
187 ; CHECK:       for.end:
188 ; CHECK-NEXT:    ret void
190 entry:
191   %cmp20 = icmp eq i64 %count, 0
192   br i1 %cmp20, label %for.end, label %for.body
194 for.body:                                         ; preds = %entry, %for.body
195   %i.023 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
196   %dst.addr.022 = phi float* [ %add.ptr8, %for.body ], [ %dst, %entry ]
197   %src.addr.021 = phi float* [ %add.ptr, %for.body ], [ %src, %entry ]
198   %0 = load float, float* %src.addr.021, align 4
199   store float %0, float* %dst.addr.022, align 4
200   %arrayidx2 = getelementptr inbounds float, float* %src.addr.021, i64 4
201   %1 = load float, float* %arrayidx2, align 4
202   %arrayidx3 = getelementptr inbounds float, float* %dst.addr.022, i64 1
203   store float %1, float* %arrayidx3, align 4
204   %arrayidx4 = getelementptr inbounds float, float* %src.addr.021, i64 2
205   %2 = load float, float* %arrayidx4, align 4
206   %arrayidx5 = getelementptr inbounds float, float* %dst.addr.022, i64 2
207   store float %2, float* %arrayidx5, align 4
208   %arrayidx6 = getelementptr inbounds float, float* %src.addr.021, i64 3
209   %3 = load float, float* %arrayidx6, align 4
210   %arrayidx7 = getelementptr inbounds float, float* %dst.addr.022, i64 3
211   store float %3, float* %arrayidx7, align 4
212   %add.ptr = getelementptr inbounds float, float* %src.addr.021, i64 %i.023
213   %add.ptr8 = getelementptr inbounds float, float* %dst.addr.022, i64 %i.023
214   %inc = add i64 %i.023, 1
215   %exitcond = icmp eq i64 %inc, %count
216   br i1 %exitcond, label %for.end, label %for.body
218 for.end:                                          ; preds = %for.body, %entry
219   ret void
222 define void @store_splat(float*, float) {
223 ; CHECK-LABEL: @store_splat(
224 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds float, float* [[TMP0:%.*]], i64 0
225 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds float, float* [[TMP0]], i64 1
226 ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds float, float* [[TMP0]], i64 2
227 ; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds float, float* [[TMP0]], i64 3
228 ; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <4 x float> undef, float [[TMP1:%.*]], i32 0
229 ; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <4 x float> [[TMP7]], float [[TMP1]], i32 1
230 ; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <4 x float> [[TMP8]], float [[TMP1]], i32 2
231 ; CHECK-NEXT:    [[TMP10:%.*]] = insertelement <4 x float> [[TMP9]], float [[TMP1]], i32 3
232 ; CHECK-NEXT:    [[TMP11:%.*]] = bitcast float* [[TMP3]] to <4 x float>*
233 ; CHECK-NEXT:    store <4 x float> [[TMP10]], <4 x float>* [[TMP11]], align 4
234 ; CHECK-NEXT:    ret void
236   %3 = getelementptr inbounds float, float* %0, i64 0
237   store float %1, float* %3, align 4
238   %4 = getelementptr inbounds float, float* %0, i64 1
239   store float %1, float* %4, align 4
240   %5 = getelementptr inbounds float, float* %0, i64 2
241   store float %1, float* %5, align 4
242   %6 = getelementptr inbounds float, float* %0, i64 3
243   store float %1, float* %6, align 4
244   ret void
247 define void @store_const(i32* %a) {
248 ; CHECK-LABEL: @store_const(
249 ; CHECK-NEXT:  entry:
250 ; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 0
251 ; CHECK-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 1
252 ; CHECK-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 2
253 ; CHECK-NEXT:    [[PTR3:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 3
254 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32* [[PTR0]] to <4 x i32>*
255 ; CHECK-NEXT:    store <4 x i32> <i32 10, i32 30, i32 20, i32 40>, <4 x i32>* [[TMP0]], align 4
256 ; CHECK-NEXT:    ret void
258 entry:
259   %ptr0 = getelementptr inbounds i32, i32* %a, i64 0
260   store i32 10, i32* %ptr0, align 4
261   %ptr1 = getelementptr inbounds i32, i32* %a, i64 1
262   store i32 30, i32* %ptr1, align 4
263   %ptr2 = getelementptr inbounds i32, i32* %a, i64 2
264   store i32 20, i32* %ptr2, align 4
265   %ptr3 = getelementptr inbounds i32, i32* %a, i64 3
266   store i32 40, i32* %ptr3, align 4
267   ret void