1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -slp-vectorizer -slp-threshold=-100 -instcombine -dce -S -mtriple=i386-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s
3; RUN: opt < %s -basic-aa -slp-vectorizer -slp-threshold=-100 -instcombine -dce -S -mtriple=i386-apple-macosx10.8.0 -mattr=+sse2 | FileCheck %s --check-prefix=SSE2
4
5target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128"
6
7; Make sure we order the operands of commutative operations so that we get
8; bigger vectorizable trees.
9
10define void @shuffle_operands1(double * noalias %from, double * noalias %to, double %v1, double %v2) {
11; CHECK-LABEL: @shuffle_operands1(
12; CHECK-NEXT:    [[TMP1:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
13; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4
14; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> poison, double [[V1:%.*]], i64 0
15; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> [[TMP3]], double [[V2:%.*]], i64 1
16; CHECK-NEXT:    [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]]
17; CHECK-NEXT:    [[TMP6:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
18; CHECK-NEXT:    store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4
19; CHECK-NEXT:    ret void
20;
21; SSE2-LABEL: @shuffle_operands1(
22; SSE2-NEXT:    [[TMP1:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
23; SSE2-NEXT:    [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4
24; SSE2-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> poison, double [[V1:%.*]], i64 0
25; SSE2-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> [[TMP3]], double [[V2:%.*]], i64 1
26; SSE2-NEXT:    [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]]
27; SSE2-NEXT:    [[TMP6:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
28; SSE2-NEXT:    store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4
29; SSE2-NEXT:    ret void
30;
31  %from_1 = getelementptr double, double *%from, i64 1
32  %v0_1 = load double , double * %from
33  %v0_2 = load double , double * %from_1
34  %v1_1 = fadd double %v0_1, %v1
35  %v1_2 = fadd double %v2, %v0_2
36  %to_2 = getelementptr double, double * %to, i64 1
37  store double %v1_1, double *%to
38  store double %v1_2, double *%to_2
39  ret void
40}
41
42define void @vecload_vs_broadcast(double * noalias %from, double * noalias %to, double %v1, double %v2) {
43; CHECK-LABEL: @vecload_vs_broadcast(
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    br label [[LP:%.*]]
46; CHECK:       lp:
47; CHECK-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
48; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
49; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
50; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0
51; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
52; CHECK-NEXT:    [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]]
53; CHECK-NEXT:    [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
54; CHECK-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4
55; CHECK-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
56; CHECK:       ext:
57; CHECK-NEXT:    ret void
58;
59; SSE2-LABEL: @vecload_vs_broadcast(
60; SSE2-NEXT:  entry:
61; SSE2-NEXT:    br label [[LP:%.*]]
62; SSE2:       lp:
63; SSE2-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
64; SSE2-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
65; SSE2-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
66; SSE2-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0
67; SSE2-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
68; SSE2-NEXT:    [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]]
69; SSE2-NEXT:    [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
70; SSE2-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4
71; SSE2-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
72; SSE2:       ext:
73; SSE2-NEXT:    ret void
74;
75entry:
76br label %lp
77
78lp:
79  %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]
80  %from_1 = getelementptr double, double *%from, i64 1
81  %v0_1 = load double , double * %from
82  %v0_2 = load double , double * %from_1
83  %v1_1 = fadd double %v0_1, %p
84  %v1_2 = fadd double %v0_1, %v0_2
85  %to_2 = getelementptr double, double * %to, i64 1
86  store double %v1_1, double *%to
87  store double %v1_2, double *%to_2
88br i1 undef, label %lp, label %ext
89
90ext:
91  ret void
92}
93
94define void @vecload_vs_broadcast2(double * noalias %from, double * noalias %to, double %v1, double %v2) {
95; CHECK-LABEL: @vecload_vs_broadcast2(
96; CHECK-NEXT:  entry:
97; CHECK-NEXT:    br label [[LP:%.*]]
98; CHECK:       lp:
99; CHECK-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
100; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
101; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
102; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0
103; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
104; CHECK-NEXT:    [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]]
105; CHECK-NEXT:    [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
106; CHECK-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4
107; CHECK-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
108; CHECK:       ext:
109; CHECK-NEXT:    ret void
110;
111; SSE2-LABEL: @vecload_vs_broadcast2(
112; SSE2-NEXT:  entry:
113; SSE2-NEXT:    br label [[LP:%.*]]
114; SSE2:       lp:
115; SSE2-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
116; SSE2-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
117; SSE2-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
118; SSE2-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0
119; SSE2-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
120; SSE2-NEXT:    [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]]
121; SSE2-NEXT:    [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
122; SSE2-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4
123; SSE2-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
124; SSE2:       ext:
125; SSE2-NEXT:    ret void
126;
127entry:
128br label %lp
129
130lp:
131  %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]
132  %from_1 = getelementptr double, double *%from, i64 1
133  %v0_1 = load double , double * %from
134  %v0_2 = load double , double * %from_1
135  %v1_1 = fadd double %p, %v0_1
136  %v1_2 = fadd double %v0_2, %v0_1
137  %to_2 = getelementptr double, double * %to, i64 1
138  store double %v1_1, double *%to
139  store double %v1_2, double *%to_2
140br i1 undef, label %lp, label %ext
141
142ext:
143  ret void
144}
145
146define void @vecload_vs_broadcast3(double * noalias %from, double * noalias %to, double %v1, double %v2) {
147; CHECK-LABEL: @vecload_vs_broadcast3(
148; CHECK-NEXT:  entry:
149; CHECK-NEXT:    br label [[LP:%.*]]
150; CHECK:       lp:
151; CHECK-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
152; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
153; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
154; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0
155; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
156; CHECK-NEXT:    [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]]
157; CHECK-NEXT:    [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
158; CHECK-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4
159; CHECK-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
160; CHECK:       ext:
161; CHECK-NEXT:    ret void
162;
163; SSE2-LABEL: @vecload_vs_broadcast3(
164; SSE2-NEXT:  entry:
165; SSE2-NEXT:    br label [[LP:%.*]]
166; SSE2:       lp:
167; SSE2-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
168; SSE2-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
169; SSE2-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
170; SSE2-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0
171; SSE2-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
172; SSE2-NEXT:    [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]]
173; SSE2-NEXT:    [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
174; SSE2-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4
175; SSE2-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
176; SSE2:       ext:
177; SSE2-NEXT:    ret void
178;
179entry:
180br label %lp
181
182lp:
183  %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]
184  %from_1 = getelementptr double, double *%from, i64 1
185  %v0_1 = load double , double * %from
186  %v0_2 = load double , double * %from_1
187  %v1_1 = fadd double %p, %v0_1
188  %v1_2 = fadd double %v0_1, %v0_2
189  %to_2 = getelementptr double, double * %to, i64 1
190  store double %v1_1, double *%to
191  store double %v1_2, double *%to_2
192br i1 undef, label %lp, label %ext
193
194ext:
195  ret void
196}
197
198define void @shuffle_nodes_match1(double * noalias %from, double * noalias %to, double %v1, double %v2) {
199; CHECK-LABEL: @shuffle_nodes_match1(
200; CHECK-NEXT:  entry:
201; CHECK-NEXT:    br label [[LP:%.*]]
202; CHECK:       lp:
203; CHECK-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
204; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
205; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
206; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
207; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1
208; CHECK-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]]
209; CHECK-NEXT:    [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
210; CHECK-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4
211; CHECK-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
212; CHECK:       ext:
213; CHECK-NEXT:    ret void
214;
215; SSE2-LABEL: @shuffle_nodes_match1(
216; SSE2-NEXT:  entry:
217; SSE2-NEXT:    br label [[LP:%.*]]
218; SSE2:       lp:
219; SSE2-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
220; SSE2-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
221; SSE2-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
222; SSE2-NEXT:    [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
223; SSE2-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1
224; SSE2-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]]
225; SSE2-NEXT:    [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
226; SSE2-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4
227; SSE2-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
228; SSE2:       ext:
229; SSE2-NEXT:    ret void
230;
231entry:
232br label %lp
233
234lp:
235  %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]
236  %from_1 = getelementptr double, double *%from, i64 1
237  %v0_1 = load double , double * %from
238  %v0_2 = load double , double * %from_1
239  %v1_1 = fadd double %v0_2, %v0_1
240  %v1_2 = fadd double %p, %v0_1
241  %to_2 = getelementptr double, double * %to, i64 1
242  store double %v1_1, double *%to
243  store double %v1_2, double *%to_2
244br i1 undef, label %lp, label %ext
245
246ext:
247  ret void
248}
249
250define void @vecload_vs_broadcast4(double * noalias %from, double * noalias %to, double %v1, double %v2) {
251; CHECK-LABEL: @vecload_vs_broadcast4(
252; CHECK-NEXT:  entry:
253; CHECK-NEXT:    br label [[LP:%.*]]
254; CHECK:       lp:
255; CHECK-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
256; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
257; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
258; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
259; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1
260; CHECK-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]]
261; CHECK-NEXT:    [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
262; CHECK-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4
263; CHECK-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
264; CHECK:       ext:
265; CHECK-NEXT:    ret void
266;
267; SSE2-LABEL: @vecload_vs_broadcast4(
268; SSE2-NEXT:  entry:
269; SSE2-NEXT:    br label [[LP:%.*]]
270; SSE2:       lp:
271; SSE2-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
272; SSE2-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
273; SSE2-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
274; SSE2-NEXT:    [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
275; SSE2-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1
276; SSE2-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]]
277; SSE2-NEXT:    [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
278; SSE2-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4
279; SSE2-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
280; SSE2:       ext:
281; SSE2-NEXT:    ret void
282;
283entry:
284br label %lp
285
286lp:
287  %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]
288  %from_1 = getelementptr double, double *%from, i64 1
289  %v0_1 = load double , double * %from
290  %v0_2 = load double , double * %from_1
291  %v1_1 = fadd double %v0_1, %v0_2
292  %v1_2 = fadd double %p, %v0_1
293  %to_2 = getelementptr double, double * %to, i64 1
294  store double %v1_1, double *%to
295  store double %v1_2, double *%to_2
296br i1 undef, label %lp, label %ext
297
298ext:
299  ret void
300}
301
302
303define void @shuffle_nodes_match2(double * noalias %from, double * noalias %to, double %v1, double %v2) {
304; CHECK-LABEL: @shuffle_nodes_match2(
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    br label [[LP:%.*]]
307; CHECK:       lp:
308; CHECK-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
309; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
310; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
311; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
312; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1
313; CHECK-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[SHUFFLE]], [[TMP2]]
314; CHECK-NEXT:    [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
315; CHECK-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4
316; CHECK-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
317; CHECK:       ext:
318; CHECK-NEXT:    ret void
319;
320; SSE2-LABEL: @shuffle_nodes_match2(
321; SSE2-NEXT:  entry:
322; SSE2-NEXT:    br label [[LP:%.*]]
323; SSE2:       lp:
324; SSE2-NEXT:    [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
325; SSE2-NEXT:    [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>*
326; SSE2-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4
327; SSE2-NEXT:    [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
328; SSE2-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1
329; SSE2-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[SHUFFLE]], [[TMP2]]
330; SSE2-NEXT:    [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>*
331; SSE2-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4
332; SSE2-NEXT:    br i1 undef, label [[LP]], label [[EXT:%.*]]
333; SSE2:       ext:
334; SSE2-NEXT:    ret void
335;
336entry:
337br label %lp
338
339lp:
340  %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]
341  %from_1 = getelementptr double, double *%from, i64 1
342  %v0_1 = load double , double * %from
343  %v0_2 = load double , double * %from_1
344  %v1_1 = fadd double %v0_1, %v0_2
345  %v1_2 = fadd double %v0_1, %p
346  %to_2 = getelementptr double, double * %to, i64 1
347  store double %v1_1, double *%to
348  store double %v1_2, double *%to_2
349br i1 undef, label %lp, label %ext
350
351ext:
352  ret void
353}
354
355; Make sure we don't scramble operands when we reorder them and destroy
356; 'good' source order.
357
358@a = common global [32000 x float] zeroinitializer, align 16
359
360define void @good_load_order() {
361; CHECK-LABEL: @good_load_order(
362; CHECK-NEXT:  entry:
363; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER:%.*]]
364; CHECK:       for.cond1.preheader:
365; CHECK-NEXT:    [[TMP0:%.*]] = load float, float* getelementptr inbounds ([32000 x float], [32000 x float]* @a, i32 0, i32 0), align 16
366; CHECK-NEXT:    br label [[FOR_BODY3:%.*]]
367; CHECK:       for.body3:
368; CHECK-NEXT:    [[TMP1:%.*]] = phi float [ [[TMP0]], [[FOR_COND1_PREHEADER]] ], [ [[TMP14:%.*]], [[FOR_BODY3]] ]
369; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY3]] ]
370; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVARS_IV]] to i32
371; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
372; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP3]]
373; CHECK-NEXT:    [[TMP4:%.*]] = trunc i64 [[INDVARS_IV]] to i32
374; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP4]]
375; CHECK-NEXT:    [[TMP5:%.*]] = trunc i64 [[INDVARS_IV]] to i32
376; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[TMP5]], 4
377; CHECK-NEXT:    [[ARRAYIDX31:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP6]]
378; CHECK-NEXT:    [[TMP7:%.*]] = bitcast float* [[ARRAYIDX]] to <4 x float>*
379; CHECK-NEXT:    [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[TMP7]], align 4
380; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0
381; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 5, i32 6>
382; CHECK-NEXT:    [[TMP11:%.*]] = fmul <4 x float> [[TMP8]], [[TMP10]]
383; CHECK-NEXT:    [[TMP12:%.*]] = bitcast float* [[ARRAYIDX5]] to <4 x float>*
384; CHECK-NEXT:    store <4 x float> [[TMP11]], <4 x float>* [[TMP12]], align 4
385; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5
386; CHECK-NEXT:    [[TMP13:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
387; CHECK-NEXT:    [[ARRAYIDX41:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP13]]
388; CHECK-NEXT:    [[TMP14]] = load float, float* [[ARRAYIDX41]], align 4
389; CHECK-NEXT:    [[TMP15:%.*]] = extractelement <4 x float> [[TMP8]], i64 3
390; CHECK-NEXT:    [[MUL45:%.*]] = fmul float [[TMP14]], [[TMP15]]
391; CHECK-NEXT:    store float [[MUL45]], float* [[ARRAYIDX31]], align 4
392; CHECK-NEXT:    [[TMP16:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
393; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[TMP16]], 31995
394; CHECK-NEXT:    br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_END:%.*]]
395; CHECK:       for.end:
396; CHECK-NEXT:    ret void
397;
398; SSE2-LABEL: @good_load_order(
399; SSE2-NEXT:  entry:
400; SSE2-NEXT:    br label [[FOR_COND1_PREHEADER:%.*]]
401; SSE2:       for.cond1.preheader:
402; SSE2-NEXT:    [[TMP0:%.*]] = load float, float* getelementptr inbounds ([32000 x float], [32000 x float]* @a, i32 0, i32 0), align 16
403; SSE2-NEXT:    br label [[FOR_BODY3:%.*]]
404; SSE2:       for.body3:
405; SSE2-NEXT:    [[TMP1:%.*]] = phi float [ [[TMP0]], [[FOR_COND1_PREHEADER]] ], [ [[TMP14:%.*]], [[FOR_BODY3]] ]
406; SSE2-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY3]] ]
407; SSE2-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVARS_IV]] to i32
408; SSE2-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
409; SSE2-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP3]]
410; SSE2-NEXT:    [[TMP4:%.*]] = trunc i64 [[INDVARS_IV]] to i32
411; SSE2-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP4]]
412; SSE2-NEXT:    [[TMP5:%.*]] = trunc i64 [[INDVARS_IV]] to i32
413; SSE2-NEXT:    [[TMP6:%.*]] = add i32 [[TMP5]], 4
414; SSE2-NEXT:    [[ARRAYIDX31:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP6]]
415; SSE2-NEXT:    [[TMP7:%.*]] = bitcast float* [[ARRAYIDX]] to <4 x float>*
416; SSE2-NEXT:    [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[TMP7]], align 4
417; SSE2-NEXT:    [[TMP9:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0
418; SSE2-NEXT:    [[TMP10:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 5, i32 6>
419; SSE2-NEXT:    [[TMP11:%.*]] = fmul <4 x float> [[TMP8]], [[TMP10]]
420; SSE2-NEXT:    [[TMP12:%.*]] = bitcast float* [[ARRAYIDX5]] to <4 x float>*
421; SSE2-NEXT:    store <4 x float> [[TMP11]], <4 x float>* [[TMP12]], align 4
422; SSE2-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5
423; SSE2-NEXT:    [[TMP13:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
424; SSE2-NEXT:    [[ARRAYIDX41:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP13]]
425; SSE2-NEXT:    [[TMP14]] = load float, float* [[ARRAYIDX41]], align 4
426; SSE2-NEXT:    [[TMP15:%.*]] = extractelement <4 x float> [[TMP8]], i64 3
427; SSE2-NEXT:    [[MUL45:%.*]] = fmul float [[TMP14]], [[TMP15]]
428; SSE2-NEXT:    store float [[MUL45]], float* [[ARRAYIDX31]], align 4
429; SSE2-NEXT:    [[TMP16:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
430; SSE2-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[TMP16]], 31995
431; SSE2-NEXT:    br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_END:%.*]]
432; SSE2:       for.end:
433; SSE2-NEXT:    ret void
434;
435entry:
436  br label %for.cond1.preheader
437
438for.cond1.preheader:
439  %0 = load float, float* getelementptr inbounds ([32000 x float], [32000 x float]* @a, i64 0, i64 0), align 16
440  br label %for.body3
441
442for.body3:
443  %1 = phi float [ %0, %for.cond1.preheader ], [ %10, %for.body3 ]
444  %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body3 ]
445  %2 = add nsw i64 %indvars.iv, 1
446  %arrayidx = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %2
447  %3 = load float, float* %arrayidx, align 4
448  %arrayidx5 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %indvars.iv
449  %mul6 = fmul float %3, %1
450  store float %mul6, float* %arrayidx5, align 4
451  %4 = add nsw i64 %indvars.iv, 2
452  %arrayidx11 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %4
453  %5 = load float, float* %arrayidx11, align 4
454  %mul15 = fmul float %5, %3
455  store float %mul15, float* %arrayidx, align 4
456  %6 = add nsw i64 %indvars.iv, 3
457  %arrayidx21 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %6
458  %7 = load float, float* %arrayidx21, align 4
459  %mul25 = fmul float %7, %5
460  store float %mul25, float* %arrayidx11, align 4
461  %8 = add nsw i64 %indvars.iv, 4
462  %arrayidx31 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %8
463  %9 = load float, float* %arrayidx31, align 4
464  %mul35 = fmul float %9, %7
465  store float %mul35, float* %arrayidx21, align 4
466  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 5
467  %arrayidx41 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %indvars.iv.next
468  %10 = load float, float* %arrayidx41, align 4
469  %mul45 = fmul float %10, %9
470  store float %mul45, float* %arrayidx31, align 4
471  %11 = trunc i64 %indvars.iv.next to i32
472  %cmp2 = icmp slt i32 %11, 31995
473  br i1 %cmp2, label %for.body3, label %for.end
474
475for.end:
476  ret void
477}
478
479; Check vectorization of following code for double data type-
480;  c[0] = a[0]+b[0];
481;  c[1] = b[1]+a[1]; // swapped b[1] and a[1]
482
483define void @load_reorder_double(double* nocapture %c, double* noalias nocapture readonly %a, double* noalias nocapture readonly %b){
484; CHECK-LABEL: @load_reorder_double(
485; CHECK-NEXT:    [[TMP1:%.*]] = bitcast double* [[B:%.*]] to <2 x double>*
486; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4
487; CHECK-NEXT:    [[TMP3:%.*]] = bitcast double* [[A:%.*]] to <2 x double>*
488; CHECK-NEXT:    [[TMP4:%.*]] = load <2 x double>, <2 x double>* [[TMP3]], align 4
489; CHECK-NEXT:    [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]]
490; CHECK-NEXT:    [[TMP6:%.*]] = bitcast double* [[C:%.*]] to <2 x double>*
491; CHECK-NEXT:    store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4
492; CHECK-NEXT:    ret void
493;
494; SSE2-LABEL: @load_reorder_double(
495; SSE2-NEXT:    [[TMP1:%.*]] = bitcast double* [[B:%.*]] to <2 x double>*
496; SSE2-NEXT:    [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4
497; SSE2-NEXT:    [[TMP3:%.*]] = bitcast double* [[A:%.*]] to <2 x double>*
498; SSE2-NEXT:    [[TMP4:%.*]] = load <2 x double>, <2 x double>* [[TMP3]], align 4
499; SSE2-NEXT:    [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]]
500; SSE2-NEXT:    [[TMP6:%.*]] = bitcast double* [[C:%.*]] to <2 x double>*
501; SSE2-NEXT:    store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4
502; SSE2-NEXT:    ret void
503;
504  %1 = load double, double* %a
505  %2 = load double, double* %b
506  %3 = fadd double %1, %2
507  store double %3, double* %c
508  %4 = getelementptr inbounds double, double* %b, i64 1
509  %5 = load double, double* %4
510  %6 = getelementptr inbounds double, double* %a, i64 1
511  %7 = load double, double* %6
512  %8 = fadd double %5, %7
513  %9 = getelementptr inbounds double, double* %c, i64 1
514  store double %8, double* %9
515  ret void
516}
517
518; Check vectorization of following code for float data type-
519;  c[0] = a[0]+b[0];
520;  c[1] = b[1]+a[1]; // swapped b[1] and a[1]
521;  c[2] = a[2]+b[2];
522;  c[3] = a[3]+b[3];
523
524define void @load_reorder_float(float* nocapture %c, float* noalias nocapture readonly %a, float* noalias nocapture readonly %b){
525; CHECK-LABEL: @load_reorder_float(
526; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float* [[A:%.*]] to <4 x float>*
527; CHECK-NEXT:    [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4
528; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float* [[B:%.*]] to <4 x float>*
529; CHECK-NEXT:    [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4
530; CHECK-NEXT:    [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]]
531; CHECK-NEXT:    [[TMP6:%.*]] = bitcast float* [[C:%.*]] to <4 x float>*
532; CHECK-NEXT:    store <4 x float> [[TMP5]], <4 x float>* [[TMP6]], align 4
533; CHECK-NEXT:    ret void
534;
535; SSE2-LABEL: @load_reorder_float(
536; SSE2-NEXT:    [[TMP1:%.*]] = bitcast float* [[A:%.*]] to <4 x float>*
537; SSE2-NEXT:    [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4
538; SSE2-NEXT:    [[TMP3:%.*]] = bitcast float* [[B:%.*]] to <4 x float>*
539; SSE2-NEXT:    [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4
540; SSE2-NEXT:    [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]]
541; SSE2-NEXT:    [[TMP6:%.*]] = bitcast float* [[C:%.*]] to <4 x float>*
542; SSE2-NEXT:    store <4 x float> [[TMP5]], <4 x float>* [[TMP6]], align 4
543; SSE2-NEXT:    ret void
544;
545  %1 = load float, float* %a
546  %2 = load float, float* %b
547  %3 = fadd float %1, %2
548  store float %3, float* %c
549  %4 = getelementptr inbounds float, float* %b, i64 1
550  %5 = load float, float* %4
551  %6 = getelementptr inbounds float, float* %a, i64 1
552  %7 = load float, float* %6
553  %8 = fadd float %5, %7
554  %9 = getelementptr inbounds float, float* %c, i64 1
555  store float %8, float* %9
556  %10 = getelementptr inbounds float, float* %a, i64 2
557  %11 = load float, float* %10
558  %12 = getelementptr inbounds float, float* %b, i64 2
559  %13 = load float, float* %12
560  %14 = fadd float %11, %13
561  %15 = getelementptr inbounds float, float* %c, i64 2
562  store float %14, float* %15
563  %16 = getelementptr inbounds float, float* %a, i64 3
564  %17 = load float, float* %16
565  %18 = getelementptr inbounds float, float* %b, i64 3
566  %19 = load float, float* %18
567  %20 = fadd float %17, %19
568  %21 = getelementptr inbounds float, float* %c, i64 3
569  store float %20, float* %21
570  ret void
571}
572
573; Check we properly reorder the below code so that it gets vectorized optimally-
574; a[0] = (b[0]+c[0])+d[0];
575; a[1] = d[1]+(b[1]+c[1]);
576; a[2] = (b[2]+c[2])+d[2];
577; a[3] = (b[3]+c[3])+d[3];
578
579define void @opcode_reorder(float* noalias nocapture %a, float* noalias nocapture readonly %b, float* noalias nocapture readonly %c,float* noalias nocapture readonly %d) {
580; CHECK-LABEL: @opcode_reorder(
581; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float* [[B:%.*]] to <4 x float>*
582; CHECK-NEXT:    [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4
583; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float* [[C:%.*]] to <4 x float>*
584; CHECK-NEXT:    [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4
585; CHECK-NEXT:    [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]]
586; CHECK-NEXT:    [[TMP6:%.*]] = bitcast float* [[D:%.*]] to <4 x float>*
587; CHECK-NEXT:    [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[TMP6]], align 4
588; CHECK-NEXT:    [[TMP8:%.*]] = fadd <4 x float> [[TMP7]], [[TMP5]]
589; CHECK-NEXT:    [[TMP9:%.*]] = bitcast float* [[A:%.*]] to <4 x float>*
590; CHECK-NEXT:    store <4 x float> [[TMP8]], <4 x float>* [[TMP9]], align 4
591; CHECK-NEXT:    ret void
592;
593; SSE2-LABEL: @opcode_reorder(
594; SSE2-NEXT:    [[TMP1:%.*]] = bitcast float* [[B:%.*]] to <4 x float>*
595; SSE2-NEXT:    [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4
596; SSE2-NEXT:    [[TMP3:%.*]] = bitcast float* [[C:%.*]] to <4 x float>*
597; SSE2-NEXT:    [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4
598; SSE2-NEXT:    [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]]
599; SSE2-NEXT:    [[TMP6:%.*]] = bitcast float* [[D:%.*]] to <4 x float>*
600; SSE2-NEXT:    [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[TMP6]], align 4
601; SSE2-NEXT:    [[TMP8:%.*]] = fadd <4 x float> [[TMP7]], [[TMP5]]
602; SSE2-NEXT:    [[TMP9:%.*]] = bitcast float* [[A:%.*]] to <4 x float>*
603; SSE2-NEXT:    store <4 x float> [[TMP8]], <4 x float>* [[TMP9]], align 4
604; SSE2-NEXT:    ret void
605;
606  %1 = load float, float* %b
607  %2 = load float, float* %c
608  %3 = fadd float %1, %2
609  %4 = load float, float* %d
610  %5 = fadd float %3, %4
611  store float %5, float* %a
612  %6 = getelementptr inbounds float, float* %d, i64 1
613  %7 = load float, float* %6
614  %8 = getelementptr inbounds float, float* %b, i64 1
615  %9 = load float, float* %8
616  %10 = getelementptr inbounds float, float* %c, i64 1
617  %11 = load float, float* %10
618  %12 = fadd float %9, %11
619  %13 = fadd float %7, %12
620  %14 = getelementptr inbounds float, float* %a, i64 1
621  store float %13, float* %14
622  %15 = getelementptr inbounds float, float* %b, i64 2
623  %16 = load float, float* %15
624  %17 = getelementptr inbounds float, float* %c, i64 2
625  %18 = load float, float* %17
626  %19 = fadd float %16, %18
627  %20 = getelementptr inbounds float, float* %d, i64 2
628  %21 = load float, float* %20
629  %22 = fadd float %19, %21
630  %23 = getelementptr inbounds float, float* %a, i64 2
631  store float %22, float* %23
632  %24 = getelementptr inbounds float, float* %b, i64 3
633  %25 = load float, float* %24
634  %26 = getelementptr inbounds float, float* %c, i64 3
635  %27 = load float, float* %26
636  %28 = fadd float %25, %27
637  %29 = getelementptr inbounds float, float* %d, i64 3
638  %30 = load float, float* %29
639  %31 = fadd float %28, %30
640  %32 = getelementptr inbounds float, float* %a, i64 3
641  store float %31, float* %32
642  ret void
643}
644