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