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