1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -slp-vectorizer -S -mtriple=i386-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s
3
4target 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"
5target triple = "i386-apple-macosx10.8.0"
6
7;int test(double *G) {
8;  G[0] = 1+G[5]*4;
9;  G[1] = 6+G[6]*3;
10;  G[2] = 7+G[5]*4;
11;  G[3] = 8+G[6]*4;
12;}
13
14define i32 @test(double* nocapture %G) {
15; CHECK-LABEL: @test(
16; CHECK-NEXT:  entry:
17; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds double, double* [[G:%.*]], i64 5
18; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[ARRAYIDX]] to <2 x double>*
19; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 8
20; CHECK-NEXT:    [[TMP2:%.*]] = fmul <2 x double> [[TMP1]], <double 4.000000e+00, double 3.000000e+00>
21; CHECK-NEXT:    [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], <double 1.000000e+00, double 6.000000e+00>
22; CHECK-NEXT:    [[TMP4:%.*]] = bitcast double* [[G]] to <2 x double>*
23; CHECK-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 8
24; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x double> [[TMP2]], i32 0
25; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds double, double* [[G]], i64 2
26; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
27; CHECK-NEXT:    [[MUL11:%.*]] = fmul double [[TMP6]], 4.000000e+00
28; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x double> poison, double [[TMP5]], i32 0
29; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <2 x double> [[TMP7]], double [[MUL11]], i32 1
30; CHECK-NEXT:    [[TMP9:%.*]] = fadd <2 x double> [[TMP8]], <double 7.000000e+00, double 8.000000e+00>
31; CHECK-NEXT:    [[TMP10:%.*]] = bitcast double* [[ARRAYIDX9]] to <2 x double>*
32; CHECK-NEXT:    store <2 x double> [[TMP9]], <2 x double>* [[TMP10]], align 8
33; CHECK-NEXT:    ret i32 undef
34;
35entry:
36  %arrayidx = getelementptr inbounds double, double* %G, i64 5
37  %0 = load double, double* %arrayidx, align 8
38  %mul = fmul double %0, 4.000000e+00
39  %add = fadd double %mul, 1.000000e+00
40  store double %add, double* %G, align 8
41  %arrayidx2 = getelementptr inbounds double, double* %G, i64 6
42  %1 = load double, double* %arrayidx2, align 8
43  %mul3 = fmul double %1, 3.000000e+00
44  %add4 = fadd double %mul3, 6.000000e+00
45  %arrayidx5 = getelementptr inbounds double, double* %G, i64 1
46  store double %add4, double* %arrayidx5, align 8
47  %add8 = fadd double %mul, 7.000000e+00
48  %arrayidx9 = getelementptr inbounds double, double* %G, i64 2
49  store double %add8, double* %arrayidx9, align 8
50  %mul11 = fmul double %1, 4.000000e+00
51  %add12 = fadd double %mul11, 8.000000e+00
52  %arrayidx13 = getelementptr inbounds double, double* %G, i64 3
53  store double %add12, double* %arrayidx13, align 8
54  ret i32 undef
55}
56
57;int foo(double *A, int n) {
58;  A[0] = A[0] * 7.9 * n + 6.0;
59;  A[1] = A[1] * 7.7 * n + 2.0;
60;  A[2] = A[2] * 7.6 * n + 3.0;
61;  A[3] = A[3] * 7.4 * n + 4.0;
62;}
63
64define i32 @foo(double* nocapture %A, i32 %n) {
65; CHECK-LABEL: @foo(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[N:%.*]] to double
68; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[A:%.*]] to <4 x double>*
69; CHECK-NEXT:    [[TMP1:%.*]] = load <4 x double>, <4 x double>* [[TMP0]], align 8
70; CHECK-NEXT:    [[TMP2:%.*]] = fmul <4 x double> [[TMP1]], <double 7.900000e+00, double 7.700000e+00, double 7.600000e+00, double 7.400000e+00>
71; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x double> poison, double [[CONV]], i32 0
72; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[TMP3]], <4 x double> poison, <4 x i32> zeroinitializer
73; CHECK-NEXT:    [[TMP4:%.*]] = fmul <4 x double> [[SHUFFLE]], [[TMP2]]
74; CHECK-NEXT:    [[TMP5:%.*]] = fadd <4 x double> [[TMP4]], <double 6.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00>
75; CHECK-NEXT:    [[TMP6:%.*]] = bitcast double* [[A]] to <4 x double>*
76; CHECK-NEXT:    store <4 x double> [[TMP5]], <4 x double>* [[TMP6]], align 8
77; CHECK-NEXT:    ret i32 undef
78;
79entry:
80  %0 = load double, double* %A, align 8
81  %mul = fmul double %0, 7.900000e+00
82  %conv = sitofp i32 %n to double
83  %mul1 = fmul double %conv, %mul
84  %add = fadd double %mul1, 6.000000e+00
85  store double %add, double* %A, align 8
86  %arrayidx3 = getelementptr inbounds double, double* %A, i64 1
87  %1 = load double, double* %arrayidx3, align 8
88  %mul4 = fmul double %1, 7.700000e+00
89  %mul6 = fmul double %conv, %mul4
90  %add7 = fadd double %mul6, 2.000000e+00
91  store double %add7, double* %arrayidx3, align 8
92  %arrayidx9 = getelementptr inbounds double, double* %A, i64 2
93  %2 = load double, double* %arrayidx9, align 8
94  %mul10 = fmul double %2, 7.600000e+00
95  %mul12 = fmul double %conv, %mul10
96  %add13 = fadd double %mul12, 3.000000e+00
97  store double %add13, double* %arrayidx9, align 8
98  %arrayidx15 = getelementptr inbounds double, double* %A, i64 3
99  %3 = load double, double* %arrayidx15, align 8
100  %mul16 = fmul double %3, 7.400000e+00
101  %mul18 = fmul double %conv, %mul16
102  %add19 = fadd double %mul18, 4.000000e+00
103  store double %add19, double* %arrayidx15, align 8
104  ret i32 undef
105}
106
107; int test2(double *G, int k) {
108;   if (k) {
109;     G[0] = 1+G[5]*4;
110;     G[1] = 6+G[6]*3;
111;   } else {
112;     G[2] = 7+G[5]*4;
113;     G[3] = 8+G[6]*3;
114;   }
115; }
116
117; We can't merge the gather sequences because one does not dominate the other.
118
119define i32 @test2(double* nocapture %G, i32 %k) {
120; CHECK-LABEL: @test2(
121; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[K:%.*]], 0
122; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds double, double* [[G:%.*]], i64 5
123; CHECK-NEXT:    [[TMP3:%.*]] = load double, double* [[TMP2]], align 8
124; CHECK-NEXT:    [[TMP4:%.*]] = fmul double [[TMP3]], 4.000000e+00
125; CHECK-NEXT:    br i1 [[TMP1]], label [[TMP13:%.*]], label [[TMP5:%.*]]
126; CHECK:       5:
127; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds double, double* [[G]], i64 6
128; CHECK-NEXT:    [[TMP7:%.*]] = load double, double* [[TMP6]], align 8
129; CHECK-NEXT:    [[TMP8:%.*]] = fmul double [[TMP7]], 3.000000e+00
130; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <2 x double> poison, double [[TMP4]], i32 0
131; CHECK-NEXT:    [[TMP10:%.*]] = insertelement <2 x double> [[TMP9]], double [[TMP8]], i32 1
132; CHECK-NEXT:    [[TMP11:%.*]] = fadd <2 x double> [[TMP10]], <double 1.000000e+00, double 6.000000e+00>
133; CHECK-NEXT:    [[TMP12:%.*]] = bitcast double* [[G]] to <2 x double>*
134; CHECK-NEXT:    store <2 x double> [[TMP11]], <2 x double>* [[TMP12]], align 8
135; CHECK-NEXT:    br label [[TMP22:%.*]]
136; CHECK:       13:
137; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds double, double* [[G]], i64 2
138; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds double, double* [[G]], i64 6
139; CHECK-NEXT:    [[TMP16:%.*]] = load double, double* [[TMP15]], align 8
140; CHECK-NEXT:    [[TMP17:%.*]] = fmul double [[TMP16]], 3.000000e+00
141; CHECK-NEXT:    [[TMP18:%.*]] = insertelement <2 x double> poison, double [[TMP4]], i32 0
142; CHECK-NEXT:    [[TMP19:%.*]] = insertelement <2 x double> [[TMP18]], double [[TMP17]], i32 1
143; CHECK-NEXT:    [[TMP20:%.*]] = fadd <2 x double> [[TMP19]], <double 7.000000e+00, double 8.000000e+00>
144; CHECK-NEXT:    [[TMP21:%.*]] = bitcast double* [[TMP14]] to <2 x double>*
145; CHECK-NEXT:    store <2 x double> [[TMP20]], <2 x double>* [[TMP21]], align 8
146; CHECK-NEXT:    br label [[TMP22]]
147; CHECK:       22:
148; CHECK-NEXT:    ret i32 undef
149;
150  %1 = icmp eq i32 %k, 0
151  %2 = getelementptr inbounds double, double* %G, i64 5
152  %3 = load double, double* %2, align 8
153  %4 = fmul double %3, 4.000000e+00
154  br i1 %1, label %12, label %5
155
156; <label>:5                                       ; preds = %0
157  %6 = fadd double %4, 1.000000e+00
158  store double %6, double* %G, align 8
159  %7 = getelementptr inbounds double, double* %G, i64 6
160  %8 = load double, double* %7, align 8
161  %9 = fmul double %8, 3.000000e+00
162  %10 = fadd double %9, 6.000000e+00
163  %11 = getelementptr inbounds double, double* %G, i64 1
164  store double %10, double* %11, align 8
165  br label %20
166
167; <label>:12                                      ; preds = %0
168  %13 = fadd double %4, 7.000000e+00
169  %14 = getelementptr inbounds double, double* %G, i64 2
170  store double %13, double* %14, align 8
171  %15 = getelementptr inbounds double, double* %G, i64 6
172  %16 = load double, double* %15, align 8
173  %17 = fmul double %16, 3.000000e+00
174  %18 = fadd double %17, 8.000000e+00
175  %19 = getelementptr inbounds double, double* %G, i64 3
176  store double %18, double* %19, align 8
177  br label %20
178
179; <label>:20                                      ; preds = %12, %5
180  ret i32 undef
181}
182
183
184;int foo(double *A, int n) {
185;  A[0] = A[0] * 7.9 * n + 6.0;
186;  A[1] = A[1] * 7.9 * n + 6.0;
187;  A[2] = A[2] * 7.9 * n + 6.0;
188;  A[3] = A[3] * 7.9 * n + 6.0;
189;}
190
191define i32 @foo4(double* nocapture %A, i32 %n) {
192; CHECK-LABEL: @foo4(
193; CHECK-NEXT:  entry:
194; CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[N:%.*]] to double
195; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[A:%.*]] to <4 x double>*
196; CHECK-NEXT:    [[TMP1:%.*]] = load <4 x double>, <4 x double>* [[TMP0]], align 8
197; CHECK-NEXT:    [[TMP2:%.*]] = fmul <4 x double> [[TMP1]], <double 7.900000e+00, double 7.900000e+00, double 7.900000e+00, double 7.900000e+00>
198; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x double> poison, double [[CONV]], i32 0
199; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[TMP3]], <4 x double> poison, <4 x i32> zeroinitializer
200; CHECK-NEXT:    [[TMP4:%.*]] = fmul <4 x double> [[SHUFFLE]], [[TMP2]]
201; CHECK-NEXT:    [[TMP5:%.*]] = fadd <4 x double> [[TMP4]], <double 6.000000e+00, double 6.000000e+00, double 6.000000e+00, double 6.000000e+00>
202; CHECK-NEXT:    [[TMP6:%.*]] = bitcast double* [[A]] to <4 x double>*
203; CHECK-NEXT:    store <4 x double> [[TMP5]], <4 x double>* [[TMP6]], align 8
204; CHECK-NEXT:    ret i32 undef
205;
206entry:
207  %0 = load double, double* %A, align 8
208  %mul = fmul double %0, 7.900000e+00
209  %conv = sitofp i32 %n to double
210  %mul1 = fmul double %conv, %mul
211  %add = fadd double %mul1, 6.000000e+00
212  store double %add, double* %A, align 8
213  %arrayidx3 = getelementptr inbounds double, double* %A, i64 1
214  %1 = load double, double* %arrayidx3, align 8
215  %mul4 = fmul double %1, 7.900000e+00
216  %mul6 = fmul double %conv, %mul4
217  %add7 = fadd double %mul6, 6.000000e+00
218  store double %add7, double* %arrayidx3, align 8
219  %arrayidx9 = getelementptr inbounds double, double* %A, i64 2
220  %2 = load double, double* %arrayidx9, align 8
221  %mul10 = fmul double %2, 7.900000e+00
222  %mul12 = fmul double %conv, %mul10
223  %add13 = fadd double %mul12, 6.000000e+00
224  store double %add13, double* %arrayidx9, align 8
225  %arrayidx15 = getelementptr inbounds double, double* %A, i64 3
226  %3 = load double, double* %arrayidx15, align 8
227  %mul16 = fmul double %3, 7.900000e+00
228  %mul18 = fmul double %conv, %mul16
229  %add19 = fadd double %mul18, 6.000000e+00
230  store double %add19, double* %arrayidx15, align 8
231  ret i32 undef
232}
233
234;int partial_mrg(double *A, int n) {
235;  A[0] = A[0] * n;
236;  A[1] = A[1] * n;
237;  if (n < 4) return 0;
238;  A[2] = A[2] * n;
239;  A[3] = A[3] * (n+4);
240;}
241
242define i32 @partial_mrg(double* nocapture %A, i32 %n) {
243; CHECK-LABEL: @partial_mrg(
244; CHECK-NEXT:  entry:
245; CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[N:%.*]] to double
246; CHECK-NEXT:    [[TMP0:%.*]] = bitcast double* [[A:%.*]] to <2 x double>*
247; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 8
248; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[CONV]], i32 0
249; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[CONV]], i32 1
250; CHECK-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP3]], [[TMP1]]
251; CHECK-NEXT:    [[TMP5:%.*]] = bitcast double* [[A]] to <2 x double>*
252; CHECK-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 8
253; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[N]], 4
254; CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[IF_END:%.*]]
255; CHECK:       if.end:
256; CHECK-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds double, double* [[A]], i64 2
257; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[N]], 4
258; CHECK-NEXT:    [[CONV12:%.*]] = sitofp i32 [[ADD]] to double
259; CHECK-NEXT:    [[TMP6:%.*]] = bitcast double* [[ARRAYIDX7]] to <2 x double>*
260; CHECK-NEXT:    [[TMP7:%.*]] = load <2 x double>, <2 x double>* [[TMP6]], align 8
261; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <2 x double> [[TMP2]], double [[CONV12]], i32 1
262; CHECK-NEXT:    [[TMP9:%.*]] = fmul <2 x double> [[TMP8]], [[TMP7]]
263; CHECK-NEXT:    [[TMP10:%.*]] = bitcast double* [[ARRAYIDX7]] to <2 x double>*
264; CHECK-NEXT:    store <2 x double> [[TMP9]], <2 x double>* [[TMP10]], align 8
265; CHECK-NEXT:    br label [[RETURN]]
266; CHECK:       return:
267; CHECK-NEXT:    ret i32 0
268;
269entry:
270  %0 = load double, double* %A, align 8
271  %conv = sitofp i32 %n to double
272  %mul = fmul double %conv, %0
273  store double %mul, double* %A, align 8
274  %arrayidx2 = getelementptr inbounds double, double* %A, i64 1
275  %1 = load double, double* %arrayidx2, align 8
276  %mul4 = fmul double %conv, %1
277  store double %mul4, double* %arrayidx2, align 8
278  %cmp = icmp slt i32 %n, 4
279  br i1 %cmp, label %return, label %if.end
280
281if.end:                                           ; preds = %entry
282  %arrayidx7 = getelementptr inbounds double, double* %A, i64 2
283  %2 = load double, double* %arrayidx7, align 8
284  %mul9 = fmul double %conv, %2
285  store double %mul9, double* %arrayidx7, align 8
286  %arrayidx11 = getelementptr inbounds double, double* %A, i64 3
287  %3 = load double, double* %arrayidx11, align 8
288  %add = add nsw i32 %n, 4
289  %conv12 = sitofp i32 %add to double
290  %mul13 = fmul double %conv12, %3
291  store double %mul13, double* %arrayidx11, align 8
292  br label %return
293
294return:                                           ; preds = %entry, %if.end
295  ret i32 0
296}
297
298%class.B.53.55 = type { %class.A.52.54, double }
299%class.A.52.54 = type { double, double, double }
300
301@a = external global double, align 8
302
303define void @PR19646(%class.B.53.55* %this) {
304; CHECK-LABEL: @PR19646(
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    br i1 undef, label [[IF_END13:%.*]], label [[IF_END13]]
307; CHECK:       sw.epilog7:
308; CHECK-NEXT:    [[DOTIN:%.*]] = getelementptr inbounds [[CLASS_B_53_55:%.*]], %class.B.53.55* [[THIS:%.*]], i64 0, i32 0, i32 1
309; CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[DOTIN]], align 8
310; CHECK-NEXT:    [[ADD:%.*]] = fadd double undef, 0.000000e+00
311; CHECK-NEXT:    [[ADD6:%.*]] = fadd double [[ADD]], [[TMP0]]
312; CHECK-NEXT:    [[TMP1:%.*]] = load double, double* @a, align 8
313; CHECK-NEXT:    [[ADD8:%.*]] = fadd double [[TMP1]], 0.000000e+00
314; CHECK-NEXT:    [[_DY:%.*]] = getelementptr inbounds [[CLASS_B_53_55]], %class.B.53.55* [[THIS]], i64 0, i32 0, i32 2
315; CHECK-NEXT:    [[TMP2:%.*]] = load double, double* [[_DY]], align 8
316; CHECK-NEXT:    [[ADD10:%.*]] = fadd double [[ADD8]], [[TMP2]]
317; CHECK-NEXT:    br i1 undef, label [[IF_THEN12:%.*]], label [[IF_END13]]
318; CHECK:       if.then12:
319; CHECK-NEXT:    [[TMP3:%.*]] = load double, double* undef, align 8
320; CHECK-NEXT:    br label [[IF_END13]]
321; CHECK:       if.end13:
322; CHECK-NEXT:    [[X_1:%.*]] = phi double [ 0.000000e+00, [[IF_THEN12]] ], [ [[ADD6]], [[SW_EPILOG7:%.*]] ], [ undef, [[ENTRY:%.*]] ], [ undef, [[ENTRY]] ]
323; CHECK-NEXT:    [[B_0:%.*]] = phi double [ [[TMP3]], [[IF_THEN12]] ], [ [[ADD10]], [[SW_EPILOG7]] ], [ undef, [[ENTRY]] ], [ undef, [[ENTRY]] ]
324; CHECK-NEXT:    unreachable
325;
326entry:
327  br i1 undef, label %if.end13, label %if.end13
328
329sw.epilog7:                                       ; No predecessors!
330  %.in = getelementptr inbounds %class.B.53.55, %class.B.53.55* %this, i64 0, i32 0, i32 1
331  %0 = load double, double* %.in, align 8
332  %add = fadd double undef, 0.000000e+00
333  %add6 = fadd double %add, %0
334  %1 = load double, double* @a, align 8
335  %add8 = fadd double %1, 0.000000e+00
336  %_dy = getelementptr inbounds %class.B.53.55, %class.B.53.55* %this, i64 0, i32 0, i32 2
337  %2 = load double, double* %_dy, align 8
338  %add10 = fadd double %add8, %2
339  br i1 undef, label %if.then12, label %if.end13
340
341if.then12:                                        ; preds = %sw.epilog7
342  %3 = load double, double* undef, align 8
343  br label %if.end13
344
345if.end13:                                         ; preds = %if.then12, %sw.epilog7, %entry
346  %x.1 = phi double [ 0.000000e+00, %if.then12 ], [ %add6, %sw.epilog7 ], [ undef, %entry ], [ undef, %entry ]
347  %b.0 = phi double [ %3, %if.then12 ], [ %add10, %sw.epilog7 ], [ undef, %entry], [ undef, %entry ]
348  unreachable
349}
350