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