1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -slp-vectorizer -S %s | FileCheck %s
3
4target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5target triple = "arm64-apple-darwin"
6
7declare void @use(double)
8
9; The extracts %v1.lane.0 and %v1.lane.1 should be considered free during SLP,
10; because they will be directly in a vector register on AArch64.
11define void @noop_extracts_first_2_lanes(<2 x double>* %ptr.1, <4 x double>* %ptr.2) {
12; CHECK-LABEL: @noop_extracts_first_2_lanes(
13; CHECK-NEXT:  bb:
14; CHECK-NEXT:    [[V_1:%.*]] = load <2 x double>, <2 x double>* [[PTR_1:%.*]], align 8
15; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
16; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
17; CHECK-NEXT:    [[V2_LANE_3:%.*]] = extractelement <4 x double> [[V_2]], i32 3
18; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V2_LANE_2]], i32 0
19; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[V2_LANE_3]], i32 1
20; CHECK-NEXT:    [[TMP2:%.*]] = fmul <2 x double> [[V_1]], [[TMP1]]
21; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <2 x double> [[V_1]], i32 0
22; CHECK-NEXT:    call void @use(double [[TMP3]])
23; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x double> [[V_1]], i32 1
24; CHECK-NEXT:    call void @use(double [[TMP4]])
25; CHECK-NEXT:    store <2 x double> [[TMP2]], <2 x double>* [[PTR_1]], align 8
26; CHECK-NEXT:    ret void
27;
28bb:
29  %v.1 = load <2 x double>, <2 x double>* %ptr.1, align 8
30  %v1.lane.0 = extractelement <2 x double> %v.1, i32 0
31  %v1.lane.1 = extractelement <2 x double> %v.1, i32 1
32
33  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
34  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
35  %v2.lane.3 = extractelement <4 x double> %v.2, i32 3
36
37  %a.lane.0 = fmul double %v1.lane.0, %v2.lane.2
38  %a.lane.1 = fmul double %v1.lane.1, %v2.lane.3
39
40  %a.ins.0 = insertelement <2 x double> undef, double %a.lane.0, i32 0
41  %a.ins.1 = insertelement <2 x double> %a.ins.0, double %a.lane.1, i32 1
42
43  call void @use(double %v1.lane.0)
44  call void @use(double %v1.lane.1)
45
46  store <2 x double> %a.ins.1, <2 x double>* %ptr.1, align 8
47  ret void
48}
49
50; Extracts of consecutive indices, but different vector operand.
51define void @extracts_first_2_lanes_different_vectors(<2 x double>* %ptr.1, <4 x double>* %ptr.2, <2 x double>* %ptr.3) {
52; CHECK-LABEL: @extracts_first_2_lanes_different_vectors(
53; CHECK-NEXT:  bb:
54; CHECK-NEXT:    [[V_1:%.*]] = load <2 x double>, <2 x double>* [[PTR_1:%.*]], align 8
55; CHECK-NEXT:    [[V1_LANE_0:%.*]] = extractelement <2 x double> [[V_1]], i32 0
56; CHECK-NEXT:    [[V_3:%.*]] = load <2 x double>, <2 x double>* [[PTR_3:%.*]], align 8
57; CHECK-NEXT:    [[V3_LANE_1:%.*]] = extractelement <2 x double> [[V_3]], i32 1
58; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
59; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
60; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V1_LANE_0]], i32 0
61; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[V3_LANE_1]], i32 1
62; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V2_LANE_2]], i32 0
63; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[V2_LANE_2]], i32 1
64; CHECK-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP1]], [[TMP3]]
65; CHECK-NEXT:    call void @use(double [[V1_LANE_0]])
66; CHECK-NEXT:    call void @use(double [[V3_LANE_1]])
67; CHECK-NEXT:    store <2 x double> [[TMP4]], <2 x double>* [[PTR_1]], align 8
68; CHECK-NEXT:    ret void
69;
70bb:
71  %v.1 = load <2 x double>, <2 x double>* %ptr.1, align 8
72  %v1.lane.0 = extractelement <2 x double> %v.1, i32 0
73  %v.3 = load <2 x double>, <2 x double>* %ptr.3, align 8
74  %v3.lane.1 = extractelement <2 x double> %v.3, i32 1
75
76  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
77  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
78
79  %a.lane.0 = fmul double %v1.lane.0, %v2.lane.2
80  %a.lane.1 = fmul double %v3.lane.1, %v2.lane.2
81
82  %a.ins.0 = insertelement <2 x double> undef, double %a.lane.0, i32 0
83  %a.ins.1 = insertelement <2 x double> %a.ins.0, double %a.lane.1, i32 1
84
85  call void @use(double %v1.lane.0)
86  call void @use(double %v3.lane.1)
87
88  store <2 x double> %a.ins.1, <2 x double>* %ptr.1, align 8
89  ret void
90}
91
92; The extracts %v1.lane.2 and %v1.lane.3 should be considered free during SLP,
93; because they will be directly in a vector register on AArch64.
94define void @noop_extract_second_2_lanes(<4 x double>* %ptr.1, <4 x double>* %ptr.2) {
95; CHECK-LABEL: @noop_extract_second_2_lanes(
96; CHECK-NEXT:  bb:
97; CHECK-NEXT:    [[V_1:%.*]] = load <4 x double>, <4 x double>* [[PTR_1:%.*]], align 8
98; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <4 x double> [[V_1]], i32 2
99; CHECK-NEXT:    [[V1_LANE_3:%.*]] = extractelement <4 x double> [[V_1]], i32 3
100; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
101; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
102; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V1_LANE_2]], i32 0
103; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[V1_LANE_3]], i32 1
104; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V2_LANE_2]], i32 0
105; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[V2_LANE_2]], i32 1
106; CHECK-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP1]], [[TMP3]]
107; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
108; CHECK-NEXT:    call void @use(double [[V1_LANE_2]])
109; CHECK-NEXT:    call void @use(double [[V1_LANE_3]])
110; CHECK-NEXT:    store <4 x double> [[TMP5]], <4 x double>* [[PTR_1]], align 8
111; CHECK-NEXT:    ret void
112;
113bb:
114  %v.1 = load <4 x double>, <4 x double>* %ptr.1, align 8
115  %v1.lane.2 = extractelement <4 x double> %v.1, i32 2
116  %v1.lane.3 = extractelement <4 x double> %v.1, i32 3
117
118  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
119  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
120
121  %a.lane.0 = fmul double %v1.lane.2, %v2.lane.2
122  %a.lane.1 = fmul double %v1.lane.3, %v2.lane.2
123
124  %a.ins.0 = insertelement <4 x double> undef, double %a.lane.0, i32 0
125  %a.ins.1 = insertelement <4 x double> %a.ins.0, double %a.lane.1, i32 1
126
127  call void @use(double %v1.lane.2)
128  call void @use(double %v1.lane.3)
129  store <4 x double> %a.ins.1, <4 x double>* %ptr.1, align 8
130  ret void
131}
132
133; %v1.lane.0 and %v1.lane.1 are used in reverse-order, so they won't be
134; directly in a vector register on AArch64.
135define void @extract_reverse_order(<2 x double>* %ptr.1, <4 x double>* %ptr.2) {
136; CHECK-LABEL: @extract_reverse_order(
137; CHECK-NEXT:  bb:
138; CHECK-NEXT:    [[V_1:%.*]] = load <2 x double>, <2 x double>* [[PTR_1:%.*]], align 8
139; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
140; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
141; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V2_LANE_2]], i32 0
142; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[V2_LANE_2]], i32 1
143; CHECK-NEXT:    [[TMP2:%.*]] = fmul <2 x double> [[V_1]], [[TMP1]]
144; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> poison, <2 x i32> <i32 1, i32 0>
145; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x double> [[V_1]], i32 0
146; CHECK-NEXT:    call void @use(double [[TMP4]])
147; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x double> [[V_1]], i32 1
148; CHECK-NEXT:    call void @use(double [[TMP5]])
149; CHECK-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[PTR_1]], align 8
150; CHECK-NEXT:    ret void
151;
152bb:
153  %v.1 = load <2 x double>, <2 x double>* %ptr.1, align 8
154  %v1.lane.0 = extractelement <2 x double> %v.1, i32 0
155  %v1.lane.1 = extractelement <2 x double> %v.1, i32 1
156
157  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
158  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
159
160  %a.lane.0 = fmul double %v1.lane.1, %v2.lane.2
161  %a.lane.1 = fmul double %v1.lane.0, %v2.lane.2
162
163  %a.ins.0 = insertelement <2 x double> undef, double %a.lane.0, i32 0
164  %a.ins.1 = insertelement <2 x double> %a.ins.0, double %a.lane.1, i32 1
165
166  call void @use(double %v1.lane.0)
167  call void @use(double %v1.lane.1)
168
169  store <2 x double> %a.ins.1, <2 x double>* %ptr.1, align 8
170  ret void
171}
172
173; %v1.lane.1 and %v1.lane.2 are extracted from different vector registers on AArch64.
174define void @extract_lanes_1_and_2(<4 x double>* %ptr.1, <4 x double>* %ptr.2) {
175; CHECK-LABEL: @extract_lanes_1_and_2(
176; CHECK-NEXT:  bb:
177; CHECK-NEXT:    [[V_1:%.*]] = load <4 x double>, <4 x double>* [[PTR_1:%.*]], align 8
178; CHECK-NEXT:    [[V1_LANE_1:%.*]] = extractelement <4 x double> [[V_1]], i32 1
179; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <4 x double> [[V_1]], i32 2
180; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
181; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
182; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V1_LANE_1]], i32 0
183; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[V1_LANE_2]], i32 1
184; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V2_LANE_2]], i32 0
185; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[V2_LANE_2]], i32 1
186; CHECK-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP1]], [[TMP3]]
187; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
188; CHECK-NEXT:    call void @use(double [[V1_LANE_1]])
189; CHECK-NEXT:    call void @use(double [[V1_LANE_2]])
190; CHECK-NEXT:    store <4 x double> [[TMP5]], <4 x double>* [[PTR_1]], align 8
191; CHECK-NEXT:    ret void
192;
193bb:
194  %v.1 = load <4 x double>, <4 x double>* %ptr.1, align 8
195  %v1.lane.1 = extractelement <4 x double> %v.1, i32 1
196  %v1.lane.2 = extractelement <4 x double> %v.1, i32 2
197
198  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
199  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
200
201  %a.lane.0 = fmul double %v1.lane.1, %v2.lane.2
202  %a.lane.1 = fmul double %v1.lane.2, %v2.lane.2
203
204  %a.ins.0 = insertelement <4 x double> undef, double %a.lane.0, i32 0
205  %a.ins.1 = insertelement <4 x double> %a.ins.0, double %a.lane.1, i32 1
206
207  call void @use(double %v1.lane.1)
208  call void @use(double %v1.lane.2)
209
210  store <4 x double> %a.ins.1, <4 x double>* %ptr.1, align 8
211  ret void
212}
213
214; More complex case where the extracted lanes are directly from a vector
215; register on AArch64 and should be considered free, because we can
216; directly use the source vector register.
217define void @noop_extracts_existing_vector_4_lanes(<9 x double>* %ptr.1, <4 x double>* %ptr.2) {
218; CHECK-LABEL: @noop_extracts_existing_vector_4_lanes(
219; CHECK-NEXT:  bb:
220; CHECK-NEXT:    [[V_1:%.*]] = load <9 x double>, <9 x double>* [[PTR_1:%.*]], align 8
221; CHECK-NEXT:    [[V1_LANE_0:%.*]] = extractelement <9 x double> [[V_1]], i32 0
222; CHECK-NEXT:    [[V1_LANE_1:%.*]] = extractelement <9 x double> [[V_1]], i32 1
223; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <9 x double> [[V_1]], i32 2
224; CHECK-NEXT:    [[V1_LANE_3:%.*]] = extractelement <9 x double> [[V_1]], i32 3
225; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
226; CHECK-NEXT:    [[V2_LANE_0:%.*]] = extractelement <4 x double> [[V_2]], i32 0
227; CHECK-NEXT:    [[V2_LANE_1:%.*]] = extractelement <4 x double> [[V_2]], i32 1
228; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
229; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <4 x double> poison, double [[V1_LANE_2]], i32 0
230; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <4 x double> [[TMP0]], double [[V1_LANE_3]], i32 1
231; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <4 x double> [[TMP1]], double [[V1_LANE_0]], i32 2
232; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x double> [[TMP2]], double [[V1_LANE_1]], i32 3
233; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <4 x double> poison, double [[V2_LANE_2]], i32 0
234; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <4 x double> [[TMP4]], double [[V2_LANE_0]], i32 1
235; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
236; CHECK-NEXT:    [[TMP6:%.*]] = fmul <4 x double> [[TMP3]], [[SHUFFLE]]
237; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <4 x double> [[TMP6]], <4 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
238; CHECK-NEXT:    call void @use(double [[V1_LANE_0]])
239; CHECK-NEXT:    call void @use(double [[V1_LANE_1]])
240; CHECK-NEXT:    call void @use(double [[V1_LANE_2]])
241; CHECK-NEXT:    call void @use(double [[V1_LANE_3]])
242; CHECK-NEXT:    store <9 x double> [[TMP7]], <9 x double>* [[PTR_1]], align 8
243; CHECK-NEXT:    ret void
244;
245bb:
246  %v.1 = load <9 x double>, <9 x double>* %ptr.1, align 8
247  %v1.lane.0 = extractelement <9 x double> %v.1, i32 0
248  %v1.lane.1 = extractelement <9 x double> %v.1, i32 1
249  %v1.lane.2 = extractelement <9 x double> %v.1, i32 2
250  %v1.lane.3 = extractelement <9 x double> %v.1, i32 3
251  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
252  %v2.lane.0 = extractelement <4 x double> %v.2, i32 0
253  %v2.lane.1 = extractelement <4 x double> %v.2, i32 1
254  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
255  %a.lane.0 = fmul double %v1.lane.2, %v2.lane.2
256  %a.lane.1 = fmul double %v1.lane.3, %v2.lane.2
257  %a.lane.2 = fmul double %v1.lane.0, %v2.lane.2
258  %a.lane.3 = fmul double %v1.lane.1, %v2.lane.0
259  %a.ins.0 = insertelement <9 x double> undef, double %a.lane.0, i32 0
260  %a.ins.1 = insertelement <9 x double> %a.ins.0, double %a.lane.1, i32 1
261  %a.ins.2 = insertelement <9 x double> %a.ins.1, double %a.lane.2, i32 2
262  %a.ins.3 = insertelement <9 x double> %a.ins.2, double %a.lane.3, i32 3
263  call void @use(double %v1.lane.0)
264  call void @use(double %v1.lane.1)
265  call void @use(double %v1.lane.2)
266  call void @use(double %v1.lane.3)
267  store <9 x double> %a.ins.3, <9 x double>* %ptr.1, align 8
268  ret void
269}
270
271; Extracted lanes are not used in the right order, so we cannot reuse the
272; source vector registers directly.
273define void @extracts_jumbled_4_lanes(<9 x double>* %ptr.1, <4 x double>* %ptr.2) {
274; CHECK-LABEL: @extracts_jumbled_4_lanes(
275; CHECK-NEXT:  bb:
276; CHECK-NEXT:    [[V_1:%.*]] = load <9 x double>, <9 x double>* [[PTR_1:%.*]], align 8
277; CHECK-NEXT:    [[V1_LANE_0:%.*]] = extractelement <9 x double> [[V_1]], i32 0
278; CHECK-NEXT:    [[V1_LANE_1:%.*]] = extractelement <9 x double> [[V_1]], i32 1
279; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <9 x double> [[V_1]], i32 2
280; CHECK-NEXT:    [[V1_LANE_3:%.*]] = extractelement <9 x double> [[V_1]], i32 3
281; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
282; CHECK-NEXT:    [[V2_LANE_0:%.*]] = extractelement <4 x double> [[V_2]], i32 0
283; CHECK-NEXT:    [[V2_LANE_1:%.*]] = extractelement <4 x double> [[V_2]], i32 1
284; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
285; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <4 x double> poison, double [[V1_LANE_0]], i32 0
286; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <4 x double> [[TMP0]], double [[V1_LANE_2]], i32 1
287; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <4 x double> [[TMP1]], double [[V1_LANE_1]], i32 2
288; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x double> [[TMP2]], double [[V1_LANE_3]], i32 3
289; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <4 x double> poison, double [[V2_LANE_2]], i32 0
290; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <4 x double> [[TMP4]], double [[V2_LANE_1]], i32 1
291; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <4 x double> [[TMP5]], double [[V2_LANE_2]], i32 2
292; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <4 x double> [[TMP6]], double [[V2_LANE_0]], i32 3
293; CHECK-NEXT:    [[TMP8:%.*]] = fmul <4 x double> [[TMP3]], [[TMP7]]
294; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <4 x double> [[TMP8]], <4 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
295; CHECK-NEXT:    call void @use(double [[V1_LANE_0]])
296; CHECK-NEXT:    call void @use(double [[V1_LANE_1]])
297; CHECK-NEXT:    call void @use(double [[V1_LANE_2]])
298; CHECK-NEXT:    call void @use(double [[V1_LANE_3]])
299; CHECK-NEXT:    store <9 x double> [[TMP9]], <9 x double>* [[PTR_1]], align 8
300; CHECK-NEXT:    ret void
301;
302bb:
303  %v.1 = load <9 x double>, <9 x double>* %ptr.1, align 8
304  %v1.lane.0 = extractelement <9 x double> %v.1, i32 0
305  %v1.lane.1 = extractelement <9 x double> %v.1, i32 1
306  %v1.lane.2 = extractelement <9 x double> %v.1, i32 2
307  %v1.lane.3 = extractelement <9 x double> %v.1, i32 3
308  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
309  %v2.lane.0 = extractelement <4 x double> %v.2, i32 0
310  %v2.lane.1 = extractelement <4 x double> %v.2, i32 1
311  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
312  %a.lane.0 = fmul double %v1.lane.0, %v2.lane.2
313  %a.lane.1 = fmul double %v1.lane.2, %v2.lane.1
314  %a.lane.2 = fmul double %v1.lane.1, %v2.lane.2
315  %a.lane.3 = fmul double %v1.lane.3, %v2.lane.0
316  %a.ins.0 = insertelement <9 x double> undef, double %a.lane.0, i32 0
317  %a.ins.1 = insertelement <9 x double> %a.ins.0, double %a.lane.1, i32 1
318  %a.ins.2 = insertelement <9 x double> %a.ins.1, double %a.lane.2, i32 2
319  %a.ins.3 = insertelement <9 x double> %a.ins.2, double %a.lane.3, i32 3
320  call void @use(double %v1.lane.0)
321  call void @use(double %v1.lane.1)
322  call void @use(double %v1.lane.2)
323  call void @use(double %v1.lane.3)
324  store <9 x double> %a.ins.3, <9 x double>* %ptr.1, align 8
325  ret void
326}
327
328
329; Even more complex case where the extracted lanes are directly from a vector
330; register on AArch64 and should be considered free, because we can
331; directly use the source vector register.
332define void @noop_extracts_9_lanes(<9 x double>* %ptr.1, <4 x double>* %ptr.2) {
333; CHECK-LABEL: @noop_extracts_9_lanes(
334; CHECK-NEXT:  bb:
335; CHECK-NEXT:    [[V_1:%.*]] = load <9 x double>, <9 x double>* [[PTR_1:%.*]], align 8
336; CHECK-NEXT:    [[V1_LANE_0:%.*]] = extractelement <9 x double> [[V_1]], i32 0
337; CHECK-NEXT:    [[V1_LANE_1:%.*]] = extractelement <9 x double> [[V_1]], i32 1
338; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <9 x double> [[V_1]], i32 2
339; CHECK-NEXT:    [[V1_LANE_3:%.*]] = extractelement <9 x double> [[V_1]], i32 3
340; CHECK-NEXT:    [[V1_LANE_4:%.*]] = extractelement <9 x double> [[V_1]], i32 4
341; CHECK-NEXT:    [[V1_LANE_5:%.*]] = extractelement <9 x double> [[V_1]], i32 5
342; CHECK-NEXT:    [[V1_LANE_6:%.*]] = extractelement <9 x double> [[V_1]], i32 6
343; CHECK-NEXT:    [[V1_LANE_7:%.*]] = extractelement <9 x double> [[V_1]], i32 7
344; CHECK-NEXT:    [[V1_LANE_8:%.*]] = extractelement <9 x double> [[V_1]], i32 8
345; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
346; CHECK-NEXT:    [[V2_LANE_0:%.*]] = extractelement <4 x double> [[V_2]], i32 0
347; CHECK-NEXT:    [[V2_LANE_1:%.*]] = extractelement <4 x double> [[V_2]], i32 1
348; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
349; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <8 x double> poison, double [[V1_LANE_3]], i32 0
350; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <8 x double> [[TMP0]], double [[V1_LANE_4]], i32 1
351; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <8 x double> [[TMP1]], double [[V1_LANE_5]], i32 2
352; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <8 x double> [[TMP2]], double [[V1_LANE_6]], i32 3
353; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <8 x double> [[TMP3]], double [[V1_LANE_7]], i32 4
354; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <8 x double> [[TMP4]], double [[V1_LANE_8]], i32 5
355; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <8 x double> [[TMP5]], double [[V1_LANE_0]], i32 6
356; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <8 x double> [[TMP6]], double [[V1_LANE_1]], i32 7
357; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <8 x double> poison, double [[V2_LANE_0]], i32 0
358; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <8 x double> [[TMP8]], double [[V2_LANE_2]], i32 1
359; CHECK-NEXT:    [[TMP10:%.*]] = insertelement <8 x double> [[TMP9]], double [[V2_LANE_1]], i32 2
360; CHECK-NEXT:    [[SHUFFLE1:%.*]] = shufflevector <8 x double> [[TMP10]], <8 x double> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 0, i32 1, i32 0, i32 1, i32 2>
361; CHECK-NEXT:    [[TMP11:%.*]] = fmul <8 x double> [[TMP7]], [[SHUFFLE1]]
362; CHECK-NEXT:    [[A_LANE_8:%.*]] = fmul double [[V1_LANE_2]], [[V2_LANE_0]]
363; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef>
364; CHECK-NEXT:    [[A_INS_8:%.*]] = insertelement <9 x double> [[TMP12]], double [[A_LANE_8]], i32 8
365; CHECK-NEXT:    [[TMP13:%.*]] = insertelement <8 x double> poison, double [[V1_LANE_6]], i32 0
366; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <8 x double> [[TMP13]], double [[V1_LANE_7]], i32 1
367; CHECK-NEXT:    [[TMP15:%.*]] = insertelement <8 x double> [[TMP14]], double [[V1_LANE_8]], i32 2
368; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <8 x double> [[TMP15]], double [[V1_LANE_0]], i32 3
369; CHECK-NEXT:    [[TMP17:%.*]] = insertelement <8 x double> [[TMP16]], double [[V1_LANE_1]], i32 4
370; CHECK-NEXT:    [[TMP18:%.*]] = insertelement <8 x double> [[TMP17]], double [[V1_LANE_2]], i32 5
371; CHECK-NEXT:    [[TMP19:%.*]] = insertelement <8 x double> [[TMP18]], double [[V1_LANE_3]], i32 6
372; CHECK-NEXT:    [[TMP20:%.*]] = insertelement <8 x double> [[TMP19]], double [[V1_LANE_4]], i32 7
373; CHECK-NEXT:    [[TMP21:%.*]] = insertelement <8 x double> poison, double [[V2_LANE_2]], i32 0
374; CHECK-NEXT:    [[TMP22:%.*]] = insertelement <8 x double> [[TMP21]], double [[V2_LANE_1]], i32 1
375; CHECK-NEXT:    [[TMP23:%.*]] = insertelement <8 x double> [[TMP22]], double [[V2_LANE_0]], i32 2
376; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 0, i32 1, i32 2, i32 0, i32 1>
377; CHECK-NEXT:    [[TMP24:%.*]] = fmul <8 x double> [[TMP20]], [[SHUFFLE]]
378; CHECK-NEXT:    [[B_LANE_8:%.*]] = fmul double [[V1_LANE_5]], [[V2_LANE_0]]
379; CHECK-NEXT:    [[TMP25:%.*]] = shufflevector <8 x double> [[TMP24]], <8 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef>
380; CHECK-NEXT:    [[B_INS_8:%.*]] = insertelement <9 x double> [[TMP25]], double [[B_LANE_8]], i32 8
381; CHECK-NEXT:    [[RES:%.*]] = fsub <9 x double> [[A_INS_8]], [[B_INS_8]]
382; CHECK-NEXT:    store <9 x double> [[RES]], <9 x double>* [[PTR_1]], align 8
383; CHECK-NEXT:    ret void
384;
385bb:
386  %v.1 = load <9 x double>, <9 x double>* %ptr.1, align 8
387  %v1.lane.0 = extractelement <9 x double> %v.1, i32 0
388  %v1.lane.1 = extractelement <9 x double> %v.1, i32 1
389  %v1.lane.2 = extractelement <9 x double> %v.1, i32 2
390  %v1.lane.3 = extractelement <9 x double> %v.1, i32 3
391  %v1.lane.4 = extractelement <9 x double> %v.1, i32 4
392  %v1.lane.5 = extractelement <9 x double> %v.1, i32 5
393  %v1.lane.6 = extractelement <9 x double> %v.1, i32 6
394  %v1.lane.7 = extractelement <9 x double> %v.1, i32 7
395  %v1.lane.8 = extractelement <9 x double> %v.1, i32 8
396
397  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
398  %v2.lane.0 = extractelement <4 x double> %v.2, i32 0
399  %v2.lane.1 = extractelement <4 x double> %v.2, i32 1
400  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
401
402  %a.lane.0 = fmul double %v1.lane.3, %v2.lane.0
403  %a.lane.1 = fmul double %v1.lane.4, %v2.lane.2
404  %a.lane.2 = fmul double %v1.lane.5, %v2.lane.1
405  %a.lane.3 = fmul double %v1.lane.6, %v2.lane.0
406  %a.lane.4 = fmul double %v1.lane.7, %v2.lane.2
407  %a.lane.5 = fmul double %v1.lane.8, %v2.lane.0
408  %a.lane.6 = fmul double %v1.lane.0, %v2.lane.2
409  %a.lane.7 = fmul double %v1.lane.1, %v2.lane.1
410  %a.lane.8 = fmul double %v1.lane.2, %v2.lane.0
411
412  %a.ins.0 = insertelement <9 x double> undef, double %a.lane.0, i32 0
413  %a.ins.1 = insertelement <9 x double> %a.ins.0, double %a.lane.1, i32 1
414  %a.ins.2 = insertelement <9 x double> %a.ins.1, double %a.lane.2, i32 2
415  %a.ins.3 = insertelement <9 x double> %a.ins.2, double %a.lane.3, i32 3
416  %a.ins.4 = insertelement <9 x double> %a.ins.3, double %a.lane.4, i32 4
417  %a.ins.5 = insertelement <9 x double> %a.ins.4, double %a.lane.5, i32 5
418  %a.ins.6 = insertelement <9 x double> %a.ins.5, double %a.lane.6, i32 6
419  %a.ins.7 = insertelement <9 x double> %a.ins.6, double %a.lane.7, i32 7
420  %a.ins.8 = insertelement <9 x double> %a.ins.7, double %a.lane.8, i32 8
421
422  %b.lane.0 = fmul double %v1.lane.6, %v2.lane.2
423  %b.lane.1 = fmul double %v1.lane.7, %v2.lane.1
424  %b.lane.2 = fmul double %v1.lane.8, %v2.lane.0
425  %b.lane.3 = fmul double %v1.lane.0, %v2.lane.2
426  %b.lane.4 = fmul double %v1.lane.1, %v2.lane.1
427  %b.lane.5 = fmul double %v1.lane.2, %v2.lane.0
428  %b.lane.6 = fmul double %v1.lane.3, %v2.lane.2
429  %b.lane.7 = fmul double %v1.lane.4, %v2.lane.1
430  %b.lane.8 = fmul double %v1.lane.5, %v2.lane.0
431
432  %b.ins.0 = insertelement <9 x double> undef, double %b.lane.0, i32 0
433  %b.ins.1 = insertelement <9 x double> %b.ins.0, double %b.lane.1, i32 1
434  %b.ins.2 = insertelement <9 x double> %b.ins.1, double %b.lane.2, i32 2
435  %b.ins.3 = insertelement <9 x double> %b.ins.2, double %b.lane.3, i32 3
436  %b.ins.4 = insertelement <9 x double> %b.ins.3, double %b.lane.4, i32 4
437  %b.ins.5 = insertelement <9 x double> %b.ins.4, double %b.lane.5, i32 5
438  %b.ins.6 = insertelement <9 x double> %b.ins.5, double %b.lane.6, i32 6
439  %b.ins.7 = insertelement <9 x double> %b.ins.6, double %b.lane.7, i32 7
440  %b.ins.8 = insertelement <9 x double> %b.ins.7, double %b.lane.8, i32 8
441
442  %res = fsub <9 x double> %a.ins.8, %b.ins.8
443  store <9 x double> %res, <9 x double>* %ptr.1, align 8
444  ret void
445}
446
447; Extracted lanes used in first fmul chain are not used in the right order, so
448; we cannot reuse the source vector registers directly.
449define void @first_mul_chain_jumbled(<9 x double>* %ptr.1, <4 x double>* %ptr.2) {
450; CHECK-LABEL: @first_mul_chain_jumbled(
451; CHECK-NEXT:  bb:
452; CHECK-NEXT:    [[V_1:%.*]] = load <9 x double>, <9 x double>* [[PTR_1:%.*]], align 8
453; CHECK-NEXT:    [[V1_LANE_0:%.*]] = extractelement <9 x double> [[V_1]], i32 0
454; CHECK-NEXT:    [[V1_LANE_1:%.*]] = extractelement <9 x double> [[V_1]], i32 1
455; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <9 x double> [[V_1]], i32 2
456; CHECK-NEXT:    [[V1_LANE_3:%.*]] = extractelement <9 x double> [[V_1]], i32 3
457; CHECK-NEXT:    [[V1_LANE_4:%.*]] = extractelement <9 x double> [[V_1]], i32 4
458; CHECK-NEXT:    [[V1_LANE_5:%.*]] = extractelement <9 x double> [[V_1]], i32 5
459; CHECK-NEXT:    [[V1_LANE_6:%.*]] = extractelement <9 x double> [[V_1]], i32 6
460; CHECK-NEXT:    [[V1_LANE_7:%.*]] = extractelement <9 x double> [[V_1]], i32 7
461; CHECK-NEXT:    [[V1_LANE_8:%.*]] = extractelement <9 x double> [[V_1]], i32 8
462; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
463; CHECK-NEXT:    [[V2_LANE_0:%.*]] = extractelement <4 x double> [[V_2]], i32 0
464; CHECK-NEXT:    [[V2_LANE_1:%.*]] = extractelement <4 x double> [[V_2]], i32 1
465; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
466; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <8 x double> poison, double [[V1_LANE_4]], i32 0
467; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <8 x double> [[TMP0]], double [[V1_LANE_3]], i32 1
468; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <8 x double> [[TMP1]], double [[V1_LANE_6]], i32 2
469; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <8 x double> [[TMP2]], double [[V1_LANE_5]], i32 3
470; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <8 x double> [[TMP3]], double [[V1_LANE_8]], i32 4
471; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <8 x double> [[TMP4]], double [[V1_LANE_7]], i32 5
472; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <8 x double> [[TMP5]], double [[V1_LANE_1]], i32 6
473; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <8 x double> [[TMP6]], double [[V1_LANE_0]], i32 7
474; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <8 x double> poison, double [[V2_LANE_1]], i32 0
475; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <8 x double> [[TMP8]], double [[V2_LANE_0]], i32 1
476; CHECK-NEXT:    [[TMP10:%.*]] = insertelement <8 x double> [[TMP9]], double [[V2_LANE_2]], i32 2
477; CHECK-NEXT:    [[SHUFFLE1:%.*]] = shufflevector <8 x double> [[TMP10]], <8 x double> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 1, i32 2, i32 0, i32 1, i32 2>
478; CHECK-NEXT:    [[TMP11:%.*]] = fmul <8 x double> [[TMP7]], [[SHUFFLE1]]
479; CHECK-NEXT:    [[A_LANE_8:%.*]] = fmul double [[V1_LANE_2]], [[V2_LANE_1]]
480; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef>
481; CHECK-NEXT:    [[A_INS_8:%.*]] = insertelement <9 x double> [[TMP12]], double [[A_LANE_8]], i32 8
482; CHECK-NEXT:    [[TMP13:%.*]] = insertelement <8 x double> poison, double [[V1_LANE_6]], i32 0
483; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <8 x double> [[TMP13]], double [[V1_LANE_7]], i32 1
484; CHECK-NEXT:    [[TMP15:%.*]] = insertelement <8 x double> [[TMP14]], double [[V1_LANE_8]], i32 2
485; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <8 x double> [[TMP15]], double [[V1_LANE_0]], i32 3
486; CHECK-NEXT:    [[TMP17:%.*]] = insertelement <8 x double> [[TMP16]], double [[V1_LANE_1]], i32 4
487; CHECK-NEXT:    [[TMP18:%.*]] = insertelement <8 x double> [[TMP17]], double [[V1_LANE_2]], i32 5
488; CHECK-NEXT:    [[TMP19:%.*]] = insertelement <8 x double> [[TMP18]], double [[V1_LANE_3]], i32 6
489; CHECK-NEXT:    [[TMP20:%.*]] = insertelement <8 x double> [[TMP19]], double [[V1_LANE_4]], i32 7
490; CHECK-NEXT:    [[TMP21:%.*]] = fmul <8 x double> [[TMP20]], [[SHUFFLE1]]
491; CHECK-NEXT:    [[B_LANE_8:%.*]] = fmul double [[V1_LANE_5]], [[V2_LANE_0]]
492; CHECK-NEXT:    [[TMP22:%.*]] = shufflevector <8 x double> [[TMP21]], <8 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef>
493; CHECK-NEXT:    [[B_INS_8:%.*]] = insertelement <9 x double> [[TMP22]], double [[B_LANE_8]], i32 8
494; CHECK-NEXT:    [[RES:%.*]] = fsub <9 x double> [[A_INS_8]], [[B_INS_8]]
495; CHECK-NEXT:    store <9 x double> [[RES]], <9 x double>* [[PTR_1]], align 8
496; CHECK-NEXT:    ret void
497;
498bb:
499  %v.1 = load <9 x double>, <9 x double>* %ptr.1, align 8
500  %v1.lane.0 = extractelement <9 x double> %v.1, i32 0
501  %v1.lane.1 = extractelement <9 x double> %v.1, i32 1
502  %v1.lane.2 = extractelement <9 x double> %v.1, i32 2
503  %v1.lane.3 = extractelement <9 x double> %v.1, i32 3
504  %v1.lane.4 = extractelement <9 x double> %v.1, i32 4
505  %v1.lane.5 = extractelement <9 x double> %v.1, i32 5
506  %v1.lane.6 = extractelement <9 x double> %v.1, i32 6
507  %v1.lane.7 = extractelement <9 x double> %v.1, i32 7
508  %v1.lane.8 = extractelement <9 x double> %v.1, i32 8
509
510  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
511  %v2.lane.0 = extractelement <4 x double> %v.2, i32 0
512  %v2.lane.1 = extractelement <4 x double> %v.2, i32 1
513  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
514
515  %a.lane.0 = fmul double %v1.lane.4, %v2.lane.1
516  %a.lane.1 = fmul double %v1.lane.3, %v2.lane.0
517  %a.lane.2 = fmul double %v1.lane.6, %v2.lane.2
518  %a.lane.3 = fmul double %v1.lane.5, %v2.lane.0
519  %a.lane.4 = fmul double %v1.lane.8, %v2.lane.2
520  %a.lane.5 = fmul double %v1.lane.7, %v2.lane.1
521  %a.lane.6 = fmul double %v1.lane.1, %v2.lane.0
522  %a.lane.7 = fmul double %v1.lane.0, %v2.lane.2
523  %a.lane.8 = fmul double %v1.lane.2, %v2.lane.1
524
525  %a.ins.0 = insertelement <9 x double> undef, double %a.lane.0, i32 0
526  %a.ins.1 = insertelement <9 x double> %a.ins.0, double %a.lane.1, i32 1
527  %a.ins.2 = insertelement <9 x double> %a.ins.1, double %a.lane.2, i32 2
528  %a.ins.3 = insertelement <9 x double> %a.ins.2, double %a.lane.3, i32 3
529  %a.ins.4 = insertelement <9 x double> %a.ins.3, double %a.lane.4, i32 4
530  %a.ins.5 = insertelement <9 x double> %a.ins.4, double %a.lane.5, i32 5
531  %a.ins.6 = insertelement <9 x double> %a.ins.5, double %a.lane.6, i32 6
532  %a.ins.7 = insertelement <9 x double> %a.ins.6, double %a.lane.7, i32 7
533  %a.ins.8 = insertelement <9 x double> %a.ins.7, double %a.lane.8, i32 8
534
535  %b.lane.0 = fmul double %v1.lane.6, %v2.lane.1
536  %b.lane.1 = fmul double %v1.lane.7, %v2.lane.0
537  %b.lane.2 = fmul double %v1.lane.8, %v2.lane.2
538  %b.lane.3 = fmul double %v1.lane.0, %v2.lane.0
539  %b.lane.4 = fmul double %v1.lane.1, %v2.lane.2
540  %b.lane.5 = fmul double %v1.lane.2, %v2.lane.1
541  %b.lane.6 = fmul double %v1.lane.3, %v2.lane.0
542  %b.lane.7 = fmul double %v1.lane.4, %v2.lane.2
543  %b.lane.8 = fmul double %v1.lane.5, %v2.lane.0
544
545  %b.ins.0 = insertelement <9 x double> undef, double %b.lane.0, i32 0
546  %b.ins.1 = insertelement <9 x double> %b.ins.0, double %b.lane.1, i32 1
547  %b.ins.2 = insertelement <9 x double> %b.ins.1, double %b.lane.2, i32 2
548  %b.ins.3 = insertelement <9 x double> %b.ins.2, double %b.lane.3, i32 3
549  %b.ins.4 = insertelement <9 x double> %b.ins.3, double %b.lane.4, i32 4
550  %b.ins.5 = insertelement <9 x double> %b.ins.4, double %b.lane.5, i32 5
551  %b.ins.6 = insertelement <9 x double> %b.ins.5, double %b.lane.6, i32 6
552  %b.ins.7 = insertelement <9 x double> %b.ins.6, double %b.lane.7, i32 7
553  %b.ins.8 = insertelement <9 x double> %b.ins.7, double %b.lane.8, i32 8
554
555  %res = fsub <9 x double> %a.ins.8, %b.ins.8
556  store <9 x double> %res, <9 x double>* %ptr.1, align 8
557  ret void
558}
559
560; Extracted lanes used in both fmul chain are not used in the right order, so
561; we cannot reuse the source vector registers directly.
562define void @first_and_second_mul_chain_jumbled(<9 x double>* %ptr.1, <4 x double>* %ptr.2) {
563; CHECK-LABEL: @first_and_second_mul_chain_jumbled(
564; CHECK-NEXT:  bb:
565; CHECK-NEXT:    [[V_1:%.*]] = load <9 x double>, <9 x double>* [[PTR_1:%.*]], align 8
566; CHECK-NEXT:    [[V1_LANE_0:%.*]] = extractelement <9 x double> [[V_1]], i32 0
567; CHECK-NEXT:    [[V1_LANE_1:%.*]] = extractelement <9 x double> [[V_1]], i32 1
568; CHECK-NEXT:    [[V1_LANE_2:%.*]] = extractelement <9 x double> [[V_1]], i32 2
569; CHECK-NEXT:    [[V1_LANE_3:%.*]] = extractelement <9 x double> [[V_1]], i32 3
570; CHECK-NEXT:    [[V1_LANE_4:%.*]] = extractelement <9 x double> [[V_1]], i32 4
571; CHECK-NEXT:    [[V1_LANE_5:%.*]] = extractelement <9 x double> [[V_1]], i32 5
572; CHECK-NEXT:    [[V1_LANE_6:%.*]] = extractelement <9 x double> [[V_1]], i32 6
573; CHECK-NEXT:    [[V1_LANE_7:%.*]] = extractelement <9 x double> [[V_1]], i32 7
574; CHECK-NEXT:    [[V1_LANE_8:%.*]] = extractelement <9 x double> [[V_1]], i32 8
575; CHECK-NEXT:    [[V_2:%.*]] = load <4 x double>, <4 x double>* [[PTR_2:%.*]], align 16
576; CHECK-NEXT:    [[V2_LANE_0:%.*]] = extractelement <4 x double> [[V_2]], i32 0
577; CHECK-NEXT:    [[V2_LANE_1:%.*]] = extractelement <4 x double> [[V_2]], i32 1
578; CHECK-NEXT:    [[V2_LANE_2:%.*]] = extractelement <4 x double> [[V_2]], i32 2
579; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <8 x double> poison, double [[V1_LANE_4]], i32 0
580; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <8 x double> [[TMP0]], double [[V1_LANE_3]], i32 1
581; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <8 x double> [[TMP1]], double [[V1_LANE_5]], i32 2
582; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <8 x double> [[TMP2]], double [[V1_LANE_6]], i32 3
583; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <8 x double> [[TMP3]], double [[V1_LANE_8]], i32 4
584; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <8 x double> [[TMP4]], double [[V1_LANE_7]], i32 5
585; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <8 x double> [[TMP5]], double [[V1_LANE_1]], i32 6
586; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <8 x double> [[TMP6]], double [[V1_LANE_0]], i32 7
587; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <8 x double> poison, double [[V2_LANE_0]], i32 0
588; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <8 x double> [[TMP8]], double [[V2_LANE_2]], i32 1
589; CHECK-NEXT:    [[TMP10:%.*]] = insertelement <8 x double> [[TMP9]], double [[V2_LANE_1]], i32 2
590; CHECK-NEXT:    [[SHUFFLE1:%.*]] = shufflevector <8 x double> [[TMP10]], <8 x double> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 1, i32 2, i32 0, i32 1, i32 2>
591; CHECK-NEXT:    [[TMP11:%.*]] = fmul <8 x double> [[TMP7]], [[SHUFFLE1]]
592; CHECK-NEXT:    [[A_LANE_8:%.*]] = fmul double [[V1_LANE_2]], [[V2_LANE_0]]
593; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef>
594; CHECK-NEXT:    [[A_INS_8:%.*]] = insertelement <9 x double> [[TMP12]], double [[A_LANE_8]], i32 8
595; CHECK-NEXT:    [[TMP13:%.*]] = insertelement <8 x double> poison, double [[V1_LANE_7]], i32 0
596; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <8 x double> [[TMP13]], double [[V1_LANE_6]], i32 1
597; CHECK-NEXT:    [[TMP15:%.*]] = insertelement <8 x double> [[TMP14]], double [[V1_LANE_8]], i32 2
598; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <8 x double> [[TMP15]], double [[V1_LANE_1]], i32 3
599; CHECK-NEXT:    [[TMP17:%.*]] = insertelement <8 x double> [[TMP16]], double [[V1_LANE_0]], i32 4
600; CHECK-NEXT:    [[TMP18:%.*]] = insertelement <8 x double> [[TMP17]], double [[V1_LANE_3]], i32 5
601; CHECK-NEXT:    [[TMP19:%.*]] = insertelement <8 x double> [[TMP18]], double [[V1_LANE_2]], i32 6
602; CHECK-NEXT:    [[TMP20:%.*]] = insertelement <8 x double> [[TMP19]], double [[V1_LANE_5]], i32 7
603; CHECK-NEXT:    [[TMP21:%.*]] = insertelement <8 x double> poison, double [[V2_LANE_2]], i32 0
604; CHECK-NEXT:    [[TMP22:%.*]] = insertelement <8 x double> [[TMP21]], double [[V2_LANE_1]], i32 1
605; CHECK-NEXT:    [[TMP23:%.*]] = insertelement <8 x double> [[TMP22]], double [[V2_LANE_0]], i32 2
606; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 0, i32 2, i32 0, i32 1, i32 2>
607; CHECK-NEXT:    [[TMP24:%.*]] = fmul <8 x double> [[TMP20]], [[SHUFFLE]]
608; CHECK-NEXT:    [[B_LANE_8:%.*]] = fmul double [[V1_LANE_4]], [[V2_LANE_2]]
609; CHECK-NEXT:    [[TMP25:%.*]] = shufflevector <8 x double> [[TMP24]], <8 x double> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef>
610; CHECK-NEXT:    [[B_INS_8:%.*]] = insertelement <9 x double> [[TMP25]], double [[B_LANE_8]], i32 8
611; CHECK-NEXT:    [[RES:%.*]] = fsub <9 x double> [[A_INS_8]], [[B_INS_8]]
612; CHECK-NEXT:    store <9 x double> [[RES]], <9 x double>* [[PTR_1]], align 8
613; CHECK-NEXT:    ret void
614;
615bb:
616  %v.1 = load <9 x double>, <9 x double>* %ptr.1, align 8
617  %v1.lane.0 = extractelement <9 x double> %v.1, i32 0
618  %v1.lane.1 = extractelement <9 x double> %v.1, i32 1
619  %v1.lane.2 = extractelement <9 x double> %v.1, i32 2
620  %v1.lane.3 = extractelement <9 x double> %v.1, i32 3
621  %v1.lane.4 = extractelement <9 x double> %v.1, i32 4
622  %v1.lane.5 = extractelement <9 x double> %v.1, i32 5
623  %v1.lane.6 = extractelement <9 x double> %v.1, i32 6
624  %v1.lane.7 = extractelement <9 x double> %v.1, i32 7
625  %v1.lane.8 = extractelement <9 x double> %v.1, i32 8
626
627  %v.2 = load <4 x double>, <4 x double>* %ptr.2, align 16
628  %v2.lane.0 = extractelement <4 x double> %v.2, i32 0
629  %v2.lane.1 = extractelement <4 x double> %v.2, i32 1
630  %v2.lane.2 = extractelement <4 x double> %v.2, i32 2
631
632  %a.lane.0 = fmul double %v1.lane.4, %v2.lane.0
633  %a.lane.1 = fmul double %v1.lane.3, %v2.lane.2
634  %a.lane.2 = fmul double %v1.lane.5, %v2.lane.1
635  %a.lane.3 = fmul double %v1.lane.6, %v2.lane.2
636  %a.lane.4 = fmul double %v1.lane.8, %v2.lane.1
637  %a.lane.5 = fmul double %v1.lane.7, %v2.lane.0
638  %a.lane.6 = fmul double %v1.lane.1, %v2.lane.2
639  %a.lane.7 = fmul double %v1.lane.0, %v2.lane.1
640  %a.lane.8 = fmul double %v1.lane.2, %v2.lane.0
641
642  %a.ins.0 = insertelement <9 x double> undef, double %a.lane.0, i32 0
643  %a.ins.1 = insertelement <9 x double> %a.ins.0, double %a.lane.1, i32 1
644  %a.ins.2 = insertelement <9 x double> %a.ins.1, double %a.lane.2, i32 2
645  %a.ins.3 = insertelement <9 x double> %a.ins.2, double %a.lane.3, i32 3
646  %a.ins.4 = insertelement <9 x double> %a.ins.3, double %a.lane.4, i32 4
647  %a.ins.5 = insertelement <9 x double> %a.ins.4, double %a.lane.5, i32 5
648  %a.ins.6 = insertelement <9 x double> %a.ins.5, double %a.lane.6, i32 6
649  %a.ins.7 = insertelement <9 x double> %a.ins.6, double %a.lane.7, i32 7
650  %a.ins.8 = insertelement <9 x double> %a.ins.7, double %a.lane.8, i32 8
651
652  %b.lane.0 = fmul double %v1.lane.7, %v2.lane.2
653  %b.lane.1 = fmul double %v1.lane.6, %v2.lane.1
654  %b.lane.2 = fmul double %v1.lane.8, %v2.lane.0
655  %b.lane.3 = fmul double %v1.lane.1, %v2.lane.2
656  %b.lane.4 = fmul double %v1.lane.0, %v2.lane.0
657  %b.lane.5 = fmul double %v1.lane.3, %v2.lane.2
658  %b.lane.6 = fmul double %v1.lane.2, %v2.lane.1
659  %b.lane.7 = fmul double %v1.lane.5, %v2.lane.0
660  %b.lane.8 = fmul double %v1.lane.4, %v2.lane.2
661
662  %b.ins.0 = insertelement <9 x double> undef, double %b.lane.0, i32 0
663  %b.ins.1 = insertelement <9 x double> %b.ins.0, double %b.lane.1, i32 1
664  %b.ins.2 = insertelement <9 x double> %b.ins.1, double %b.lane.2, i32 2
665  %b.ins.3 = insertelement <9 x double> %b.ins.2, double %b.lane.3, i32 3
666  %b.ins.4 = insertelement <9 x double> %b.ins.3, double %b.lane.4, i32 4
667  %b.ins.5 = insertelement <9 x double> %b.ins.4, double %b.lane.5, i32 5
668  %b.ins.6 = insertelement <9 x double> %b.ins.5, double %b.lane.6, i32 6
669  %b.ins.7 = insertelement <9 x double> %b.ins.6, double %b.lane.7, i32 7
670  %b.ins.8 = insertelement <9 x double> %b.ins.7, double %b.lane.8, i32 8
671
672  %res = fsub <9 x double> %a.ins.8, %b.ins.8
673  store <9 x double> %res, <9 x double>* %ptr.1, align 8
674  ret void
675}
676