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