1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -slp-vectorizer -dce -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s
3
4;int foo(char * restrict A, float * restrict B, float T) {
5;  A[0] = (T * B[10] + 4.0);
6;  A[1] = (T * B[11] + 5.0);
7;  A[2] = (T * B[12] + 6.0);
8;}
9
10define i32 @foo(i8* noalias nocapture %A, float* noalias nocapture %B, float %T) {
11; CHECK-LABEL: @foo(
12; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds float, float* [[B:%.*]], i64 10
13; CHECK-NEXT:    [[TMP2:%.*]] = load float, float* [[TMP1]], align 4
14; CHECK-NEXT:    [[TMP3:%.*]] = fmul float [[TMP2]], [[T:%.*]]
15; CHECK-NEXT:    [[TMP4:%.*]] = fpext float [[TMP3]] to double
16; CHECK-NEXT:    [[TMP5:%.*]] = fadd double [[TMP4]], 4.000000e+00
17; CHECK-NEXT:    [[TMP6:%.*]] = fptosi double [[TMP5]] to i8
18; CHECK-NEXT:    store i8 [[TMP6]], i8* [[A:%.*]], align 1
19; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds float, float* [[B]], i64 11
20; CHECK-NEXT:    [[TMP8:%.*]] = load float, float* [[TMP7]], align 4
21; CHECK-NEXT:    [[TMP9:%.*]] = fmul float [[TMP8]], [[T]]
22; CHECK-NEXT:    [[TMP10:%.*]] = fpext float [[TMP9]] to double
23; CHECK-NEXT:    [[TMP11:%.*]] = fadd double [[TMP10]], 5.000000e+00
24; CHECK-NEXT:    [[TMP12:%.*]] = fptosi double [[TMP11]] to i8
25; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 1
26; CHECK-NEXT:    store i8 [[TMP12]], i8* [[TMP13]], align 1
27; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds float, float* [[B]], i64 12
28; CHECK-NEXT:    [[TMP15:%.*]] = load float, float* [[TMP14]], align 4
29; CHECK-NEXT:    [[TMP16:%.*]] = fmul float [[TMP15]], [[T]]
30; CHECK-NEXT:    [[TMP17:%.*]] = fpext float [[TMP16]] to double
31; CHECK-NEXT:    [[TMP18:%.*]] = fadd double [[TMP17]], 6.000000e+00
32; CHECK-NEXT:    [[TMP19:%.*]] = fptosi double [[TMP18]] to i8
33; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 2
34; CHECK-NEXT:    store i8 [[TMP19]], i8* [[TMP20]], align 1
35; CHECK-NEXT:    ret i32 undef
36;
37  %1 = getelementptr inbounds float, float* %B, i64 10
38  %2 = load float, float* %1, align 4
39  %3 = fmul float %2, %T
40  %4 = fpext float %3 to double
41  %5 = fadd double %4, 4.000000e+00
42  %6 = fptosi double %5 to i8
43  store i8 %6, i8* %A, align 1
44  %7 = getelementptr inbounds float, float* %B, i64 11
45  %8 = load float, float* %7, align 4
46  %9 = fmul float %8, %T
47  %10 = fpext float %9 to double
48  %11 = fadd double %10, 5.000000e+00
49  %12 = fptosi double %11 to i8
50  %13 = getelementptr inbounds i8, i8* %A, i64 1
51  store i8 %12, i8* %13, align 1
52  %14 = getelementptr inbounds float, float* %B, i64 12
53  %15 = load float, float* %14, align 4
54  %16 = fmul float %15, %T
55  %17 = fpext float %16 to double
56  %18 = fadd double %17, 6.000000e+00
57  %19 = fptosi double %18 to i8
58  %20 = getelementptr inbounds i8, i8* %A, i64 2
59  store i8 %19, i8* %20, align 1
60  ret i32 undef
61}
62
63; PR41892
64define void @test_v4f32_v2f32_store(<4 x float> %f, float* %p){
65; CHECK-LABEL: @test_v4f32_v2f32_store(
66; CHECK-NEXT:    [[X0:%.*]] = extractelement <4 x float> [[F:%.*]], i64 0
67; CHECK-NEXT:    [[X1:%.*]] = extractelement <4 x float> [[F]], i64 1
68; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[X0]], i32 0
69; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[X1]], i32 1
70; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float* [[P:%.*]] to <2 x float>*
71; CHECK-NEXT:    store <2 x float> [[TMP2]], <2 x float>* [[TMP3]], align 4
72; CHECK-NEXT:    ret void
73;
74  %x0 = extractelement <4 x float> %f, i64 0
75  %x1 = extractelement <4 x float> %f, i64 1
76  %p1 = getelementptr inbounds float, float* %p, i64 1
77  store float %x0, float* %p, align 4
78  store float %x1, float* %p1, align 4
79  ret void
80}
81
82define void @test_v4f32_v2f32_splat_store(<4 x float> %f, float* %p){
83; CHECK-LABEL: @test_v4f32_v2f32_splat_store(
84; CHECK-NEXT:    [[X0:%.*]] = extractelement <4 x float> [[F:%.*]], i64 0
85; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float, float* [[P:%.*]], i64 1
86; CHECK-NEXT:    store float [[X0]], float* [[P]], align 4
87; CHECK-NEXT:    store float [[X0]], float* [[P1]], align 4
88; CHECK-NEXT:    ret void
89;
90  %x0 = extractelement <4 x float> %f, i64 0
91  %p1 = getelementptr inbounds float, float* %p, i64 1
92  store float %x0, float* %p, align 4
93  store float %x0, float* %p1, align 4
94  ret void
95}
96
97define void @test_v4f32_v3f32_store(<4 x float> %f, float* %p){
98; CHECK-LABEL: @test_v4f32_v3f32_store(
99; CHECK-NEXT:    [[X0:%.*]] = extractelement <4 x float> [[F:%.*]], i64 0
100; CHECK-NEXT:    [[X1:%.*]] = extractelement <4 x float> [[F]], i64 1
101; CHECK-NEXT:    [[X2:%.*]] = extractelement <4 x float> [[F]], i64 2
102; CHECK-NEXT:    [[P2:%.*]] = getelementptr inbounds float, float* [[P:%.*]], i64 2
103; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[X0]], i32 0
104; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[X1]], i32 1
105; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float* [[P]] to <2 x float>*
106; CHECK-NEXT:    store <2 x float> [[TMP2]], <2 x float>* [[TMP3]], align 4
107; CHECK-NEXT:    store float [[X2]], float* [[P2]], align 4
108; CHECK-NEXT:    ret void
109;
110  %x0 = extractelement <4 x float> %f, i64 0
111  %x1 = extractelement <4 x float> %f, i64 1
112  %x2 = extractelement <4 x float> %f, i64 2
113  %p1 = getelementptr inbounds float, float* %p, i64 1
114  %p2 = getelementptr inbounds float, float* %p, i64 2
115  store float %x0, float* %p, align 4
116  store float %x1, float* %p1, align 4
117  store float %x2, float* %p2, align 4
118  ret void
119}
120
121define void @test_v4f32_v3f32_splat_store(<4 x float> %f, float* %p){
122; CHECK-LABEL: @test_v4f32_v3f32_splat_store(
123; CHECK-NEXT:    [[X0:%.*]] = extractelement <4 x float> [[F:%.*]], i64 0
124; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float, float* [[P:%.*]], i64 1
125; CHECK-NEXT:    [[P2:%.*]] = getelementptr inbounds float, float* [[P]], i64 2
126; CHECK-NEXT:    store float [[X0]], float* [[P]], align 4
127; CHECK-NEXT:    store float [[X0]], float* [[P1]], align 4
128; CHECK-NEXT:    store float [[X0]], float* [[P2]], align 4
129; CHECK-NEXT:    ret void
130;
131  %x0 = extractelement <4 x float> %f, i64 0
132  %p1 = getelementptr inbounds float, float* %p, i64 1
133  %p2 = getelementptr inbounds float, float* %p, i64 2
134  store float %x0, float* %p, align 4
135  store float %x0, float* %p1, align 4
136  store float %x0, float* %p2, align 4
137  ret void
138}
139
140define void @test_v4f32_v4f32_store(<4 x float> %f, float* %p){
141; CHECK-LABEL: @test_v4f32_v4f32_store(
142; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float* [[P:%.*]] to <4 x float>*
143; CHECK-NEXT:    store <4 x float> [[F:%.*]], <4 x float>* [[TMP1]], align 4
144; CHECK-NEXT:    ret void
145;
146  %x0 = extractelement <4 x float> %f, i64 0
147  %x1 = extractelement <4 x float> %f, i64 1
148  %x2 = extractelement <4 x float> %f, i64 2
149  %x3 = extractelement <4 x float> %f, i64 3
150  %p1 = getelementptr inbounds float, float* %p, i64 1
151  %p2 = getelementptr inbounds float, float* %p, i64 2
152  %p3 = getelementptr inbounds float, float* %p, i64 3
153  store float %x0, float* %p, align 4
154  store float %x1, float* %p1, align 4
155  store float %x2, float* %p2, align 4
156  store float %x3, float* %p3, align 4
157  ret void
158}
159
160define void @test_v4f32_v4f32_splat_store(<4 x float> %f, float* %p){
161; CHECK-LABEL: @test_v4f32_v4f32_splat_store(
162; CHECK-NEXT:    [[X0:%.*]] = extractelement <4 x float> [[F:%.*]], i64 0
163; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <4 x float> poison, float [[X0]], i32 0
164; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> zeroinitializer
165; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[P:%.*]] to <4 x float>*
166; CHECK-NEXT:    store <4 x float> [[SHUFFLE]], <4 x float>* [[TMP2]], align 4
167; CHECK-NEXT:    ret void
168;
169  %x0 = extractelement <4 x float> %f, i64 0
170  %p1 = getelementptr inbounds float, float* %p, i64 1
171  %p2 = getelementptr inbounds float, float* %p, i64 2
172  %p3 = getelementptr inbounds float, float* %p, i64 3
173  store float %x0, float* %p, align 4
174  store float %x0, float* %p1, align 4
175  store float %x0, float* %p2, align 4
176  store float %x0, float* %p3, align 4
177  ret void
178}
179