brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.3 KiB · d2e3d82 Raw
751 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux -mattr=+sse2 | FileCheck %s --check-prefixes=CHECK,SSE3; RUN: opt -passes=slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux -mcpu=corei7-avx | FileCheck %s --check-prefixes=CHECK,AVX4;5; This file tests the look-ahead operand reordering heuristic.6;7;8; This checks that operand reordering will reorder the operands of the adds9; by taking into consideration the instructions beyond the immediate10; predecessors.11;12; A[0] B[0] C[0] D[0]  C[1] D[1] A[1] B[1]13;     \  /   \  /          \  /   \  /14;       -     -              -     -15;        \   /                \   /16;          +                    +17;          |                    |18;         S[0]                 S[1]19;20define void @lookahead_basic(ptr %array) {21; CHECK-LABEL: @lookahead_basic(22; CHECK-NEXT:  entry:23; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds double, ptr [[ARRAY:%.*]], i64 224; CHECK-NEXT:    [[IDX4:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 425; CHECK-NEXT:    [[IDX6:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 626; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY]], align 827; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[IDX2]], align 828; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[IDX4]], align 829; CHECK-NEXT:    [[TMP3:%.*]] = load <2 x double>, ptr [[IDX6]], align 830; CHECK-NEXT:    [[TMP4:%.*]] = fsub fast <2 x double> [[TMP0]], [[TMP1]]31; CHECK-NEXT:    [[TMP5:%.*]] = fsub fast <2 x double> [[TMP2]], [[TMP3]]32; CHECK-NEXT:    [[TMP6:%.*]] = fadd fast <2 x double> [[TMP5]], [[TMP4]]33; CHECK-NEXT:    store <2 x double> [[TMP6]], ptr [[ARRAY]], align 834; CHECK-NEXT:    ret void35;36entry:37  %idx1 = getelementptr inbounds double, ptr %array, i64 138  %idx2 = getelementptr inbounds double, ptr %array, i64 239  %idx3 = getelementptr inbounds double, ptr %array, i64 340  %idx4 = getelementptr inbounds double, ptr %array, i64 441  %idx5 = getelementptr inbounds double, ptr %array, i64 542  %idx6 = getelementptr inbounds double, ptr %array, i64 643  %idx7 = getelementptr inbounds double, ptr %array, i64 744 45  %A_0 = load double, ptr %array, align 846  %A_1 = load double, ptr %idx1, align 847  %B_0 = load double, ptr %idx2, align 848  %B_1 = load double, ptr %idx3, align 849  %C_0 = load double, ptr %idx4, align 850  %C_1 = load double, ptr %idx5, align 851  %D_0 = load double, ptr %idx6, align 852  %D_1 = load double, ptr %idx7, align 853 54  %subAB_0 = fsub fast double %A_0, %B_055  %subCD_0 = fsub fast double %C_0, %D_056 57  %subAB_1 = fsub fast double %A_1, %B_158  %subCD_1 = fsub fast double %C_1, %D_159 60  %addABCD_0 = fadd fast double %subAB_0, %subCD_061  %addCDAB_1 = fadd fast double %subCD_1, %subAB_162 63  store double %addABCD_0, ptr %array, align 864  store double %addCDAB_1, ptr %idx1, align 865  ret void66}67 68 69; Check whether the look-ahead operand reordering heuristic will avoid70; bundling the alt opcodes. The vectorized code should have no shuffles.71;72; A[0] B[0] A[0] B[0]  A[1] A[1] A[1] B[1]73;     \  /   \  /          \  /   \  /74;       +     -              -     +75;        \   /                \   /76;          +                    +77;          |                    |78;         S[0]                 S[1]79;80define void @lookahead_alt1(ptr %array) {81; CHECK-LABEL: @lookahead_alt1(82; CHECK-NEXT:  entry:83; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds double, ptr [[ARRAY:%.*]], i64 284; CHECK-NEXT:    [[IDX4:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 485; CHECK-NEXT:    [[IDX5:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 586; CHECK-NEXT:    [[IDX6:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 687; CHECK-NEXT:    [[IDX7:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 788; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY]], align 889; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[IDX2]], align 890; CHECK-NEXT:    [[TMP2:%.*]] = fsub fast <2 x double> [[TMP0]], [[TMP1]]91; CHECK-NEXT:    [[TMP3:%.*]] = fadd fast <2 x double> [[TMP0]], [[TMP1]]92; CHECK-NEXT:    [[TMP4:%.*]] = fadd fast <2 x double> [[TMP3]], [[TMP2]]93; CHECK-NEXT:    store <2 x double> [[TMP4]], ptr [[ARRAY]], align 894; CHECK-NEXT:    ret void95;96entry:97  %idx1 = getelementptr inbounds double, ptr %array, i64 198  %idx2 = getelementptr inbounds double, ptr %array, i64 299  %idx3 = getelementptr inbounds double, ptr %array, i64 3100  %idx4 = getelementptr inbounds double, ptr %array, i64 4101  %idx5 = getelementptr inbounds double, ptr %array, i64 5102  %idx6 = getelementptr inbounds double, ptr %array, i64 6103  %idx7 = getelementptr inbounds double, ptr %array, i64 7104 105  %A_0 = load double, ptr %array, align 8106  %A_1 = load double, ptr %idx1, align 8107  %B_0 = load double, ptr %idx2, align 8108  %B_1 = load double, ptr %idx3, align 8109 110  %addAB_0_L = fadd fast double %A_0, %B_0111  %subAB_0_R = fsub fast double %A_0, %B_0112 113  %subAB_1_L = fsub fast double %A_1, %B_1114  %addAB_1_R = fadd fast double %A_1, %B_1115 116  %addABCD_0 = fadd fast double %addAB_0_L, %subAB_0_R117  %addCDAB_1 = fadd fast double %subAB_1_L, %addAB_1_R118 119  store double %addABCD_0, ptr %array, align 8120  store double %addCDAB_1, ptr %idx1, align 8121  ret void122}123 124 125; This code should get vectorized all the way to the loads with shuffles for126; the alt opcodes.127;128; A[0] B[0] C[0] D[0]  C[1] D[1] A[1] B[1]129;     \  /   \  /          \  /   \  /130;       +     -              +     -131;        \   /                \   /132;          +                    +133;          |                    |134;         S[0]                 S[1]135;136define void @lookahead_alt2(ptr %array) {137; CHECK-LABEL: @lookahead_alt2(138; CHECK-NEXT:  entry:139; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds double, ptr [[ARRAY:%.*]], i64 2140; CHECK-NEXT:    [[IDX4:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 4141; CHECK-NEXT:    [[IDX6:%.*]] = getelementptr inbounds double, ptr [[ARRAY]], i64 6142; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY]], align 8143; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[IDX2]], align 8144; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[IDX4]], align 8145; CHECK-NEXT:    [[TMP3:%.*]] = load <2 x double>, ptr [[IDX6]], align 8146; CHECK-NEXT:    [[TMP4:%.*]] = fsub fast <2 x double> [[TMP2]], [[TMP3]]147; CHECK-NEXT:    [[TMP5:%.*]] = fadd fast <2 x double> [[TMP2]], [[TMP3]]148; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> [[TMP5]], <2 x i32> <i32 0, i32 3>149; CHECK-NEXT:    [[TMP7:%.*]] = fadd fast <2 x double> [[TMP0]], [[TMP1]]150; CHECK-NEXT:    [[TMP8:%.*]] = fsub fast <2 x double> [[TMP0]], [[TMP1]]151; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP8]], <2 x i32> <i32 0, i32 3>152; CHECK-NEXT:    [[TMP10:%.*]] = fadd fast <2 x double> [[TMP6]], [[TMP9]]153; CHECK-NEXT:    store <2 x double> [[TMP10]], ptr [[ARRAY]], align 8154; CHECK-NEXT:    ret void155;156entry:157  %idx1 = getelementptr inbounds double, ptr %array, i64 1158  %idx2 = getelementptr inbounds double, ptr %array, i64 2159  %idx3 = getelementptr inbounds double, ptr %array, i64 3160  %idx4 = getelementptr inbounds double, ptr %array, i64 4161  %idx5 = getelementptr inbounds double, ptr %array, i64 5162  %idx6 = getelementptr inbounds double, ptr %array, i64 6163  %idx7 = getelementptr inbounds double, ptr %array, i64 7164 165  %A_0 = load double, ptr %array, align 8166  %A_1 = load double, ptr %idx1, align 8167  %B_0 = load double, ptr %idx2, align 8168  %B_1 = load double, ptr %idx3, align 8169  %C_0 = load double, ptr %idx4, align 8170  %C_1 = load double, ptr %idx5, align 8171  %D_0 = load double, ptr %idx6, align 8172  %D_1 = load double, ptr %idx7, align 8173 174  %addAB_0 = fadd fast double %A_0, %B_0175  %subCD_0 = fsub fast double %C_0, %D_0176 177  %addCD_1 = fadd fast double %C_1, %D_1178  %subAB_1 = fsub fast double %A_1, %B_1179 180  %addABCD_0 = fadd fast double %addAB_0, %subCD_0181  %addCDAB_1 = fadd fast double %addCD_1, %subAB_1182 183  store double %addABCD_0, ptr %array, align 8184  store double %addCDAB_1, ptr %idx1, align 8185  ret void186}187 188 189;190; A[0] B[0] C[0] D[0]  A[1] B[2] A[2] B[1]191;     \  /   \  /       /  \  /   \  /192;       -     -        U     -     -193;        \   /                \   /194;          +                    +195;          |                    |196;         S[0]                 S[1]197;198; SLP should reorder the operands of the RHS add taking into consideration the cost of external uses.199; It is more profitable to reorder the operands of the RHS add, because A[1] has an external use.200 201define void @lookahead_external_uses(ptr %A, ptr %B, ptr %C, ptr %D, ptr %S, ptr %Ext1, ptr %Ext2) {202; CHECK-LABEL: @lookahead_external_uses(203; CHECK-NEXT:  entry:204; CHECK-NEXT:    [[IDXA1:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i64 1205; CHECK-NEXT:    [[IDXB2:%.*]] = getelementptr inbounds double, ptr [[B:%.*]], i64 2206; CHECK-NEXT:    [[IDXA2:%.*]] = getelementptr inbounds double, ptr [[A]], i64 2207; CHECK-NEXT:    [[C0:%.*]] = load double, ptr [[C:%.*]], align 8208; CHECK-NEXT:    [[D0:%.*]] = load double, ptr [[D:%.*]], align 8209; CHECK-NEXT:    [[B2:%.*]] = load double, ptr [[IDXB2]], align 8210; CHECK-NEXT:    [[A2:%.*]] = load double, ptr [[IDXA2]], align 8211; CHECK-NEXT:    [[A1:%.*]] = load double, ptr [[IDXA1]], align 8212; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[A]], align 8213; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B]], align 8214; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[B2]], i32 1215; CHECK-NEXT:    [[TMP3:%.*]] = fsub fast <2 x double> [[TMP0]], [[TMP2]]216; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> poison, double [[C0]], i32 0217; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <2 x double> [[TMP4]], double [[A2]], i32 1218; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <2 x double> [[TMP1]], double [[D0]], i32 0219; CHECK-NEXT:    [[TMP7:%.*]] = fsub fast <2 x double> [[TMP5]], [[TMP6]]220; CHECK-NEXT:    [[TMP8:%.*]] = fadd fast <2 x double> [[TMP3]], [[TMP7]]221; CHECK-NEXT:    store <2 x double> [[TMP8]], ptr [[S:%.*]], align 8222; CHECK-NEXT:    store double [[A1]], ptr [[EXT1:%.*]], align 8223; CHECK-NEXT:    ret void224;225entry:226 227  %IdxA1 = getelementptr inbounds double, ptr %A, i64 1228  %IdxB2 = getelementptr inbounds double, ptr %B, i64 2229  %IdxA2 = getelementptr inbounds double, ptr %A, i64 2230  %IdxB1 = getelementptr inbounds double, ptr %B, i64 1231 232  %A0 = load double, ptr %A, align 8233  %B0 = load double, ptr %B, align 8234  %C0 = load double, ptr %C, align 8235  %D0 = load double, ptr %D, align 8236 237  %A1 = load double, ptr %IdxA1, align 8238  %B2 = load double, ptr %IdxB2, align 8239  %A2 = load double, ptr %IdxA2, align 8240  %B1 = load double, ptr %IdxB1, align 8241 242  %subA0B0 = fsub fast double %A0, %B0243  %subC0D0 = fsub fast double %C0, %D0244 245  %subA1B2 = fsub fast double %A1, %B2246  %subA2B1 = fsub fast double %A2, %B1247 248  %add0 = fadd fast double %subA0B0, %subC0D0249  %add1 = fadd fast double %subA1B2, %subA2B1250 251  %IdxS1 = getelementptr inbounds double, ptr %S, i64 1252 253  store double %add0, ptr %S, align 8254  store double %add1, ptr %IdxS1, align 8255 256  ; External use257  store double %A1, ptr %Ext1, align 8258  ret void259}260 261; A[0] B[0] C[0] D[0]  A[1] B[2] A[2] B[1]262;     \  /   \  /       /  \  /   \  / \263;       -     -    U1,U2,U3  -     -  U4,U5264;        \   /                \   /265;          +                    +266;          |                    |267;         S[0]                 S[1]268;269;270; If we limit the users budget for the look-ahead heuristic to 2, then the271; look-ahead heuristic has no way of choosing B[1] (with 2 external users)272; over A[1] (with 3 external users).273; The result is that the operands are of the Add not reordered and the loads274; from A get vectorized instead of the loads from B.275;276define void @lookahead_limit_users_budget(ptr %A, ptr %B, ptr %C, ptr %D, ptr %S, ptr %Ext1, ptr %Ext2, ptr %Ext3, ptr %Ext4, ptr %Ext5) {277; CHECK-LABEL: @lookahead_limit_users_budget(278; CHECK-NEXT:  entry:279; CHECK-NEXT:    [[IDXA1:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i64 1280; CHECK-NEXT:    [[IDXB2:%.*]] = getelementptr inbounds double, ptr [[B:%.*]], i64 2281; CHECK-NEXT:    [[IDXA2:%.*]] = getelementptr inbounds double, ptr [[A]], i64 2282; CHECK-NEXT:    [[IDXB1:%.*]] = getelementptr inbounds double, ptr [[B]], i64 1283; CHECK-NEXT:    [[C0:%.*]] = load double, ptr [[C:%.*]], align 8284; CHECK-NEXT:    [[D0:%.*]] = load double, ptr [[D:%.*]], align 8285; CHECK-NEXT:    [[B2:%.*]] = load double, ptr [[IDXB2]], align 8286; CHECK-NEXT:    [[A2:%.*]] = load double, ptr [[IDXA2]], align 8287; CHECK-NEXT:    [[A1:%.*]] = load double, ptr [[IDXA1]], align 8288; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[A]], align 8289; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B]], align 8290; CHECK-NEXT:    [[B1:%.*]] = load double, ptr [[IDXB1]], align 8291; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[B2]], i32 1292; CHECK-NEXT:    [[TMP3:%.*]] = fsub fast <2 x double> [[TMP0]], [[TMP2]]293; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> poison, double [[C0]], i32 0294; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <2 x double> [[TMP4]], double [[A2]], i32 1295; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <2 x double> [[TMP1]], double [[D0]], i32 0296; CHECK-NEXT:    [[TMP7:%.*]] = fsub fast <2 x double> [[TMP5]], [[TMP6]]297; CHECK-NEXT:    [[TMP8:%.*]] = fadd fast <2 x double> [[TMP3]], [[TMP7]]298; CHECK-NEXT:    store <2 x double> [[TMP8]], ptr [[S:%.*]], align 8299; CHECK-NEXT:    store double [[A1]], ptr [[EXT1:%.*]], align 8300; CHECK-NEXT:    store double [[A1]], ptr [[EXT2:%.*]], align 8301; CHECK-NEXT:    store double [[A1]], ptr [[EXT3:%.*]], align 8302; CHECK-NEXT:    store double [[B1]], ptr [[EXT4:%.*]], align 8303; CHECK-NEXT:    store double [[B1]], ptr [[EXT5:%.*]], align 8304; CHECK-NEXT:    ret void305;306entry:307 308  %IdxA1 = getelementptr inbounds double, ptr %A, i64 1309  %IdxB2 = getelementptr inbounds double, ptr %B, i64 2310  %IdxA2 = getelementptr inbounds double, ptr %A, i64 2311  %IdxB1 = getelementptr inbounds double, ptr %B, i64 1312 313  %A0 = load double, ptr %A, align 8314  %B0 = load double, ptr %B, align 8315  %C0 = load double, ptr %C, align 8316  %D0 = load double, ptr %D, align 8317 318  %A1 = load double, ptr %IdxA1, align 8319  %B2 = load double, ptr %IdxB2, align 8320  %A2 = load double, ptr %IdxA2, align 8321  %B1 = load double, ptr %IdxB1, align 8322 323  %subA0B0 = fsub fast double %A0, %B0324  %subC0D0 = fsub fast double %C0, %D0325 326  %subA1B2 = fsub fast double %A1, %B2327  %subA2B1 = fsub fast double %A2, %B1328 329  %add0 = fadd fast double %subA0B0, %subC0D0330  %add1 = fadd fast double %subA1B2, %subA2B1331 332  %IdxS1 = getelementptr inbounds double, ptr %S, i64 1333 334  store double %add0, ptr %S, align 8335  store double %add1, ptr %IdxS1, align 8336 337  ; External uses of A1338  store double %A1, ptr %Ext1, align 8339  store double %A1, ptr %Ext2, align 8340  store double %A1, ptr %Ext3, align 8341 342  ; External uses of B1343  store double %B1, ptr %Ext4, align 8344  store double %B1, ptr %Ext5, align 8345 346  ret void347}348 349; This checks that the lookahead code does not crash when instructions with the same opcodes have different numbers of operands (in this case the calls).350 351%Class = type { i8 }352declare double @_ZN1i2ayEv(ptr)353declare double @_ZN1i2axEv()354 355define void @lookahead_crash(ptr %A, ptr %S, ptr %Arg0) {356; CHECK-LABEL: @lookahead_crash(357; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8358; CHECK-NEXT:    [[C0:%.*]] = call double @_ZN1i2ayEv(ptr [[ARG0:%.*]])359; CHECK-NEXT:    [[C1:%.*]] = call double @_ZN1i2axEv()360; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[C0]], i32 0361; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[C1]], i32 1362; CHECK-NEXT:    [[TMP4:%.*]] = fadd fast <2 x double> [[TMP1]], [[TMP3]]363; CHECK-NEXT:    store <2 x double> [[TMP4]], ptr [[S:%.*]], align 8364; CHECK-NEXT:    ret void365;366  %IdxA1 = getelementptr inbounds double, ptr %A, i64 1367 368  %A0 = load double, ptr %A, align 8369  %A1 = load double, ptr %IdxA1, align 8370 371  %C0 = call double @_ZN1i2ayEv(ptr %Arg0)372  %C1 = call double @_ZN1i2axEv()373 374  %add0 = fadd fast double %A0, %C0375  %add1 = fadd fast double %A1, %C1376 377  %IdxS1 = getelementptr inbounds double, ptr %S, i64 1378  store double %add0, ptr %S, align 8379  store double %add1, ptr %IdxS1, align 8380  ret void381}382 383; This checks that we choose to group consecutive extracts from the same vectors.384define void @ChecksExtractScores(ptr %storeArray, ptr %array, ptr %vecPtr1, ptr %vecPtr2) {385; CHECK-LABEL: @ChecksExtractScores(386; CHECK-NEXT:    [[IDX1:%.*]] = getelementptr inbounds double, ptr [[ARRAY:%.*]], i64 1387; CHECK-NEXT:    [[LOADA0:%.*]] = load double, ptr [[ARRAY]], align 4388; CHECK-NEXT:    [[LOADA1:%.*]] = load double, ptr [[IDX1]], align 4389; CHECK-NEXT:    [[LOADVEC:%.*]] = load <2 x double>, ptr [[VECPTR1:%.*]], align 4390; CHECK-NEXT:    [[LOADVEC2:%.*]] = load <2 x double>, ptr [[VECPTR2:%.*]], align 4391; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> poison, double [[LOADA0]], i32 0392; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> zeroinitializer393; CHECK-NEXT:    [[TMP3:%.*]] = fmul <2 x double> [[LOADVEC]], [[TMP2]]394; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> poison, double [[LOADA1]], i32 0395; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> poison, <2 x i32> zeroinitializer396; CHECK-NEXT:    [[TMP6:%.*]] = fmul <2 x double> [[LOADVEC2]], [[TMP5]]397; CHECK-NEXT:    [[TMP7:%.*]] = fadd <2 x double> [[TMP3]], [[TMP6]]398; CHECK-NEXT:    store <2 x double> [[TMP7]], ptr [[STOREARRAY:%.*]], align 8399; CHECK-NEXT:    ret void400;401  %idx1 = getelementptr inbounds double, ptr %array, i64 1402  %loadA0 = load double, ptr %array, align 4403  %loadA1 = load double, ptr %idx1, align 4404 405  %loadVec = load <2 x double>, ptr %vecPtr1, align 4406  %extrA0 = extractelement <2 x double> %loadVec, i32 0407  %extrA1 = extractelement <2 x double> %loadVec, i32 1408  %loadVec2 = load <2 x double>, ptr %vecPtr2, align 4409  %extrB0 = extractelement <2 x double> %loadVec2, i32 0410  %extrB1 = extractelement <2 x double> %loadVec2, i32 1411 412  %mul0 = fmul double %extrA0, %loadA0413  %mul1 = fmul double %extrA1, %loadA0414  %mul3 = fmul double %extrB0, %loadA1415  %mul4 = fmul double %extrB1, %loadA1416  %add0 = fadd double %mul0, %mul3417  %add1 = fadd double %mul1, %mul4418 419  %sidx1 = getelementptr inbounds double, ptr %storeArray, i64 1420  store double %add0, ptr %storeArray, align 8421  store double %add1, ptr %sidx1, align 8422  ret void423}424 425 426define i1 @ExtractIdxNotConstantInt1(float %a, float %b, float %c, <4 x float> %vec, i64 %idx2) {427; SSE-LABEL: @ExtractIdxNotConstantInt1(428; SSE-NEXT:    [[VECEXT_I291_I166:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 undef429; SSE-NEXT:    [[SUB14_I167:%.*]] = fsub float undef, [[VECEXT_I291_I166]]430; SSE-NEXT:    [[VECEXT_I276_I169:%.*]] = extractelement <4 x float> [[VEC]], i64 [[IDX2:%.*]]431; SSE-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i32 0432; SSE-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[C:%.*]], i32 1433; SSE-NEXT:    [[TMP3:%.*]] = insertelement <2 x float> poison, float [[SUB14_I167]], i32 0434; SSE-NEXT:    [[TMP4:%.*]] = insertelement <2 x float> [[TMP3]], float [[VECEXT_I276_I169]], i32 1435; SSE-NEXT:    [[TMP5:%.*]] = fmul <2 x float> [[TMP2]], [[TMP4]]436; SSE-NEXT:    [[TMP6:%.*]] = insertelement <2 x float> <float poison, float 3.000000e+01>, float [[B:%.*]], i32 0437; SSE-NEXT:    [[TMP7:%.*]] = fsub <2 x float> [[TMP5]], [[TMP6]]438; SSE-NEXT:    [[TMP8:%.*]] = fadd <2 x float> [[TMP7]], <float 1.000000e+01, float 2.000000e+00>439; SSE-NEXT:    [[TMP9:%.*]] = extractelement <2 x float> [[TMP8]], i32 0440; SSE-NEXT:    [[TMP10:%.*]] = extractelement <2 x float> [[TMP8]], i32 1441; SSE-NEXT:    [[MUL123_I184:%.*]] = fmul float [[TMP9]], [[TMP10]]442; SSE-NEXT:    [[CMP_I185:%.*]] = fcmp ogt float [[MUL123_I184]], 0.000000e+00443; SSE-NEXT:    ret i1 [[CMP_I185]]444;445; AVX-LABEL: @ExtractIdxNotConstantInt1(446; AVX-NEXT:    [[VECEXT_I291_I166:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 undef447; AVX-NEXT:    [[SUB14_I167:%.*]] = fsub float undef, [[VECEXT_I291_I166]]448; AVX-NEXT:    [[FM:%.*]] = fmul float [[A:%.*]], [[SUB14_I167]]449; AVX-NEXT:    [[SUB25_I168:%.*]] = fsub float [[FM]], [[B:%.*]]450; AVX-NEXT:    [[VECEXT_I276_I169:%.*]] = extractelement <4 x float> [[VEC]], i64 [[IDX2:%.*]]451; AVX-NEXT:    [[ADD36_I173:%.*]] = fadd float [[SUB25_I168]], 1.000000e+01452; AVX-NEXT:    [[MUL72_I179:%.*]] = fmul float [[C:%.*]], [[VECEXT_I276_I169]]453; AVX-NEXT:    [[ADD78_I180:%.*]] = fsub float [[MUL72_I179]], 3.000000e+01454; AVX-NEXT:    [[ADD79_I181:%.*]] = fadd float 2.000000e+00, [[ADD78_I180]]455; AVX-NEXT:    [[MUL123_I184:%.*]] = fmul float [[ADD36_I173]], [[ADD79_I181]]456; AVX-NEXT:    [[CMP_I185:%.*]] = fcmp ogt float [[MUL123_I184]], 0.000000e+00457; AVX-NEXT:    ret i1 [[CMP_I185]]458;459  %vecext.i291.i166 = extractelement <4 x float> %vec, i64 undef460  %sub14.i167 = fsub float undef, %vecext.i291.i166461  %fm = fmul float %a, %sub14.i167462  %sub25.i168 = fsub float %fm, %b463  %vecext.i276.i169 = extractelement <4 x float> %vec, i64 %idx2464  %add36.i173 = fadd float %sub25.i168, 10.0465  %mul72.i179 = fmul float %c, %vecext.i276.i169466  %add78.i180 = fsub float %mul72.i179, 30.0467  %add79.i181 = fadd float 2.0, %add78.i180468  %mul123.i184 = fmul float %add36.i173, %add79.i181469  %cmp.i185 = fcmp ogt float %mul123.i184, 0.000000e+00470  ret i1 %cmp.i185471}472 473 474define i1 @ExtractIdxNotConstantInt2(float %a, float %b, float %c, <4 x float> %vec, i64 %idx2) {475; SSE-LABEL: @ExtractIdxNotConstantInt2(476; SSE-NEXT:    [[VECEXT_I291_I166:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 1477; SSE-NEXT:    [[SUB14_I167:%.*]] = fsub float undef, [[VECEXT_I291_I166]]478; SSE-NEXT:    [[VECEXT_I276_I169:%.*]] = extractelement <4 x float> [[VEC]], i64 [[IDX2:%.*]]479; SSE-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i32 0480; SSE-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[C:%.*]], i32 1481; SSE-NEXT:    [[TMP3:%.*]] = insertelement <2 x float> poison, float [[SUB14_I167]], i32 0482; SSE-NEXT:    [[TMP4:%.*]] = insertelement <2 x float> [[TMP3]], float [[VECEXT_I276_I169]], i32 1483; SSE-NEXT:    [[TMP5:%.*]] = fmul <2 x float> [[TMP2]], [[TMP4]]484; SSE-NEXT:    [[TMP6:%.*]] = insertelement <2 x float> <float poison, float 3.000000e+01>, float [[B:%.*]], i32 0485; SSE-NEXT:    [[TMP7:%.*]] = fsub <2 x float> [[TMP5]], [[TMP6]]486; SSE-NEXT:    [[TMP8:%.*]] = fadd <2 x float> [[TMP7]], <float 1.000000e+01, float 2.000000e+00>487; SSE-NEXT:    [[TMP9:%.*]] = extractelement <2 x float> [[TMP8]], i32 0488; SSE-NEXT:    [[TMP10:%.*]] = extractelement <2 x float> [[TMP8]], i32 1489; SSE-NEXT:    [[MUL123_I184:%.*]] = fmul float [[TMP9]], [[TMP10]]490; SSE-NEXT:    [[CMP_I185:%.*]] = fcmp ogt float [[MUL123_I184]], 0.000000e+00491; SSE-NEXT:    ret i1 [[CMP_I185]]492;493; AVX-LABEL: @ExtractIdxNotConstantInt2(494; AVX-NEXT:    [[VECEXT_I291_I166:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 1495; AVX-NEXT:    [[SUB14_I167:%.*]] = fsub float undef, [[VECEXT_I291_I166]]496; AVX-NEXT:    [[FM:%.*]] = fmul float [[A:%.*]], [[SUB14_I167]]497; AVX-NEXT:    [[SUB25_I168:%.*]] = fsub float [[FM]], [[B:%.*]]498; AVX-NEXT:    [[VECEXT_I276_I169:%.*]] = extractelement <4 x float> [[VEC]], i64 [[IDX2:%.*]]499; AVX-NEXT:    [[ADD36_I173:%.*]] = fadd float [[SUB25_I168]], 1.000000e+01500; AVX-NEXT:    [[MUL72_I179:%.*]] = fmul float [[C:%.*]], [[VECEXT_I276_I169]]501; AVX-NEXT:    [[ADD78_I180:%.*]] = fsub float [[MUL72_I179]], 3.000000e+01502; AVX-NEXT:    [[ADD79_I181:%.*]] = fadd float 2.000000e+00, [[ADD78_I180]]503; AVX-NEXT:    [[MUL123_I184:%.*]] = fmul float [[ADD36_I173]], [[ADD79_I181]]504; AVX-NEXT:    [[CMP_I185:%.*]] = fcmp ogt float [[MUL123_I184]], 0.000000e+00505; AVX-NEXT:    ret i1 [[CMP_I185]]506;507  %vecext.i291.i166 = extractelement <4 x float> %vec, i64 1508  %sub14.i167 = fsub float undef, %vecext.i291.i166509  %fm = fmul float %a, %sub14.i167510  %sub25.i168 = fsub float %fm, %b511  %vecext.i276.i169 = extractelement <4 x float> %vec, i64 %idx2512  %add36.i173 = fadd float %sub25.i168, 10.0513  %mul72.i179 = fmul float %c, %vecext.i276.i169514  %add78.i180 = fsub float %mul72.i179, 30.0515  %add79.i181 = fadd float 2.0, %add78.i180516  %mul123.i184 = fmul float %add36.i173, %add79.i181517  %cmp.i185 = fcmp ogt float %mul123.i184, 0.000000e+00518  ret i1 %cmp.i185519}520 521 522define i1 @foo(float %a, float %b, float %c, <4 x float> %vec, i64 %idx2) {523; SSE-LABEL: @foo(524; SSE-NEXT:    [[VECEXT_I291_I166:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 0525; SSE-NEXT:    [[SUB14_I167:%.*]] = fsub float undef, [[VECEXT_I291_I166]]526; SSE-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i32 0527; SSE-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[C:%.*]], i32 1528; SSE-NEXT:    [[TMP3:%.*]] = shufflevector <4 x float> [[VEC]], <4 x float> poison, <2 x i32> <i32 poison, i32 1>529; SSE-NEXT:    [[TMP4:%.*]] = insertelement <2 x float> [[TMP3]], float [[SUB14_I167]], i32 0530; SSE-NEXT:    [[TMP5:%.*]] = fmul <2 x float> [[TMP2]], [[TMP4]]531; SSE-NEXT:    [[TMP6:%.*]] = insertelement <2 x float> <float poison, float 3.000000e+01>, float [[B:%.*]], i32 0532; SSE-NEXT:    [[TMP7:%.*]] = fsub <2 x float> [[TMP5]], [[TMP6]]533; SSE-NEXT:    [[TMP8:%.*]] = fadd <2 x float> [[TMP7]], <float 1.000000e+01, float 2.000000e+00>534; SSE-NEXT:    [[TMP9:%.*]] = extractelement <2 x float> [[TMP8]], i32 0535; SSE-NEXT:    [[TMP10:%.*]] = extractelement <2 x float> [[TMP8]], i32 1536; SSE-NEXT:    [[MUL123_I184:%.*]] = fmul float [[TMP9]], [[TMP10]]537; SSE-NEXT:    [[CMP_I185:%.*]] = fcmp ogt float [[MUL123_I184]], 0.000000e+00538; SSE-NEXT:    ret i1 [[CMP_I185]]539;540; AVX-LABEL: @foo(541; AVX-NEXT:    [[VECEXT_I291_I166:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 0542; AVX-NEXT:    [[SUB14_I167:%.*]] = fsub float undef, [[VECEXT_I291_I166]]543; AVX-NEXT:    [[FM:%.*]] = fmul float [[A:%.*]], [[SUB14_I167]]544; AVX-NEXT:    [[SUB25_I168:%.*]] = fsub float [[FM]], [[B:%.*]]545; AVX-NEXT:    [[VECEXT_I276_I169:%.*]] = extractelement <4 x float> [[VEC]], i64 1546; AVX-NEXT:    [[ADD36_I173:%.*]] = fadd float [[SUB25_I168]], 1.000000e+01547; AVX-NEXT:    [[MUL72_I179:%.*]] = fmul float [[C:%.*]], [[VECEXT_I276_I169]]548; AVX-NEXT:    [[ADD78_I180:%.*]] = fsub float [[MUL72_I179]], 3.000000e+01549; AVX-NEXT:    [[ADD79_I181:%.*]] = fadd float 2.000000e+00, [[ADD78_I180]]550; AVX-NEXT:    [[MUL123_I184:%.*]] = fmul float [[ADD36_I173]], [[ADD79_I181]]551; AVX-NEXT:    [[CMP_I185:%.*]] = fcmp ogt float [[MUL123_I184]], 0.000000e+00552; AVX-NEXT:    ret i1 [[CMP_I185]]553;554  %vecext.i291.i166 = extractelement <4 x float> %vec, i64 0555  %sub14.i167 = fsub float undef, %vecext.i291.i166556  %fm = fmul float %a, %sub14.i167557  %sub25.i168 = fsub float %fm, %b558  %vecext.i276.i169 = extractelement <4 x float> %vec, i64 1559  %add36.i173 = fadd float %sub25.i168, 10.0560  %mul72.i179 = fmul float %c, %vecext.i276.i169561  %add78.i180 = fsub float %mul72.i179, 30.0562  %add79.i181 = fadd float 2.0, %add78.i180563  %mul123.i184 = fmul float %add36.i173, %add79.i181564  %cmp.i185 = fcmp ogt float %mul123.i184, 0.000000e+00565  ret i1 %cmp.i185566}567 568; Same as @ChecksExtractScores, but the extratelement vector operands do not match.569define void @ChecksExtractScores_different_vectors(ptr %storeArray, ptr %array, ptr %vecPtr1, ptr %vecPtr2, ptr %vecPtr3, ptr %vecPtr4) {570;571; SSE-LABEL: @ChecksExtractScores_different_vectors(572; SSE-NEXT:    [[LOADVEC:%.*]] = load <2 x double>, ptr [[VECPTR1:%.*]], align 4573; SSE-NEXT:    [[LOADVEC2:%.*]] = load <2 x double>, ptr [[VECPTR2:%.*]], align 4574; SSE-NEXT:    [[LOADVEC3:%.*]] = load <2 x double>, ptr [[VECPTR3:%.*]], align 4575; SSE-NEXT:    [[LOADVEC4:%.*]] = load <2 x double>, ptr [[VECPTR4:%.*]], align 4576; SSE-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAY:%.*]], align 4577; SSE-NEXT:    [[TMP2:%.*]] = shufflevector <2 x double> [[LOADVEC2]], <2 x double> [[LOADVEC3]], <2 x i32> <i32 1, i32 2>578; SSE-NEXT:    [[TMP3:%.*]] = fmul <2 x double> [[TMP2]], [[TMP1]]579; SSE-NEXT:    [[TMP4:%.*]] = shufflevector <2 x double> [[TMP3]], <2 x double> poison, <2 x i32> <i32 1, i32 0>580; SSE-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[LOADVEC]], <2 x double> [[LOADVEC4]], <2 x i32> <i32 0, i32 3>581; SSE-NEXT:    [[TMP6:%.*]] = fmul <2 x double> [[TMP5]], [[TMP1]]582; SSE-NEXT:    [[TMP7:%.*]] = fadd <2 x double> [[TMP4]], [[TMP6]]583; SSE-NEXT:    store <2 x double> [[TMP7]], ptr [[STOREARRAY:%.*]], align 8584; SSE-NEXT:    ret void585;586; AVX-LABEL: @ChecksExtractScores_different_vectors(587; AVX-NEXT:    [[IDX1:%.*]] = getelementptr inbounds double, ptr [[ARRAY:%.*]], i64 1588; AVX-NEXT:    [[LOADA0:%.*]] = load double, ptr [[ARRAY]], align 4589; AVX-NEXT:    [[LOADA1:%.*]] = load double, ptr [[IDX1]], align 4590; AVX-NEXT:    [[LOADVEC:%.*]] = load <2 x double>, ptr [[VECPTR1:%.*]], align 4591; AVX-NEXT:    [[LOADVEC2:%.*]] = load <2 x double>, ptr [[VECPTR2:%.*]], align 4592; AVX-NEXT:    [[LOADVEC3:%.*]] = load <2 x double>, ptr [[VECPTR3:%.*]], align 4593; AVX-NEXT:    [[LOADVEC4:%.*]] = load <2 x double>, ptr [[VECPTR4:%.*]], align 4594; AVX-NEXT:    [[TMP1:%.*]] = shufflevector <2 x double> [[LOADVEC]], <2 x double> [[LOADVEC2]], <2 x i32> <i32 0, i32 3>595; AVX-NEXT:    [[TMP2:%.*]] = insertelement <2 x double> poison, double [[LOADA0]], i32 0596; AVX-NEXT:    [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> poison, <2 x i32> zeroinitializer597; AVX-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP1]], [[TMP3]]598; AVX-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[LOADVEC3]], <2 x double> [[LOADVEC4]], <2 x i32> <i32 0, i32 3>599; AVX-NEXT:    [[TMP6:%.*]] = insertelement <2 x double> poison, double [[LOADA1]], i32 0600; AVX-NEXT:    [[TMP7:%.*]] = shufflevector <2 x double> [[TMP6]], <2 x double> poison, <2 x i32> zeroinitializer601; AVX-NEXT:    [[TMP8:%.*]] = fmul <2 x double> [[TMP5]], [[TMP7]]602; AVX-NEXT:    [[TMP9:%.*]] = fadd <2 x double> [[TMP4]], [[TMP8]]603; AVX-NEXT:    store <2 x double> [[TMP9]], ptr [[STOREARRAY:%.*]], align 8604; AVX-NEXT:    ret void605;606  %idx1 = getelementptr inbounds double, ptr %array, i64 1607  %loadA0 = load double, ptr %array, align 4608  %loadA1 = load double, ptr %idx1, align 4609 610  %loadVec = load <2 x double>, ptr %vecPtr1, align 4611  %loadVec2 = load <2 x double>, ptr %vecPtr2, align 4612  %extrA0 = extractelement <2 x double> %loadVec, i32 0613  %extrA1 = extractelement <2 x double> %loadVec2, i32 1614  %loadVec3= load <2 x double>, ptr %vecPtr3, align 4615  %loadVec4 = load <2 x double>, ptr %vecPtr4, align 4616  %extrB0 = extractelement <2 x double> %loadVec3, i32 0617  %extrB1 = extractelement <2 x double> %loadVec4, i32 1618 619  %mul0 = fmul double %extrA0, %loadA0620  %mul1 = fmul double %extrA1, %loadA0621  %mul3 = fmul double %extrB0, %loadA1622  %mul4 = fmul double %extrB1, %loadA1623  %add0 = fadd double %mul0, %mul3624  %add1 = fadd double %mul1, %mul4625 626  %sidx1 = getelementptr inbounds double, ptr %storeArray, i64 1627  store double %add0, ptr %storeArray, align 8628  store double %add1, ptr %sidx1, align 8629  ret void630}631 632; This checks that we we prefer splats rather than reverse load vectors + shuffles.633; 2-wide splat loads in x86 use a single instruction so they are quite cheap.634define double @splat_loads(ptr %array1, ptr %array2, ptr %ptrA, ptr %ptrB) {635; SSE-LABEL: @splat_loads(636; SSE-NEXT:  entry:637; SSE-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY1:%.*]], align 8638; SSE-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAY2:%.*]], align 8639; SSE-NEXT:    [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>640; SSE-NEXT:    [[TMP3:%.*]] = fmul <2 x double> [[TMP0]], [[TMP2]]641; SSE-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP0]], [[TMP1]]642; SSE-NEXT:    [[TMP5:%.*]] = fadd <2 x double> [[TMP3]], [[TMP4]]643; SSE-NEXT:    [[TMP6:%.*]] = extractelement <2 x double> [[TMP5]], i32 0644; SSE-NEXT:    [[TMP7:%.*]] = extractelement <2 x double> [[TMP5]], i32 1645; SSE-NEXT:    [[ADD3:%.*]] = fadd double [[TMP6]], [[TMP7]]646; SSE-NEXT:    ret double [[ADD3]]647;648; AVX-LABEL: @splat_loads(649; AVX-NEXT:  entry:650; AVX-NEXT:    [[GEP_2_1:%.*]] = getelementptr inbounds double, ptr [[ARRAY2:%.*]], i64 1651; AVX-NEXT:    [[LD_2_0:%.*]] = load double, ptr [[ARRAY2]], align 8652; AVX-NEXT:    [[LD_2_1:%.*]] = load double, ptr [[GEP_2_1]], align 8653; AVX-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY1:%.*]], align 8654; AVX-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> poison, double [[LD_2_0]], i32 0655; AVX-NEXT:    [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> zeroinitializer656; AVX-NEXT:    [[TMP3:%.*]] = fmul <2 x double> [[TMP0]], [[TMP2]]657; AVX-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> poison, double [[LD_2_1]], i32 0658; AVX-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> poison, <2 x i32> zeroinitializer659; AVX-NEXT:    [[TMP6:%.*]] = fmul <2 x double> [[TMP0]], [[TMP5]]660; AVX-NEXT:    [[TMP7:%.*]] = fadd <2 x double> [[TMP3]], [[TMP6]]661; AVX-NEXT:    [[TMP8:%.*]] = extractelement <2 x double> [[TMP7]], i32 0662; AVX-NEXT:    [[TMP9:%.*]] = extractelement <2 x double> [[TMP7]], i32 1663; AVX-NEXT:    [[ADD3:%.*]] = fadd double [[TMP8]], [[TMP9]]664; AVX-NEXT:    ret double [[ADD3]]665;666entry:667  %gep_1_1 = getelementptr inbounds double, ptr %array1, i64 1668  %ld_1_0 = load double, ptr %array1, align 8669  %ld_1_1 = load double, ptr %gep_1_1, align 8670 671  %gep_2_1 = getelementptr inbounds double, ptr %array2, i64 1672  %ld_2_0 = load double, ptr %array2, align 8673  %ld_2_1 = load double, ptr %gep_2_1, align 8674 675  %mul1 = fmul double %ld_1_0, %ld_2_0676  %mul2 = fmul double %ld_1_1, %ld_2_0677 678  %mul3 = fmul double %ld_1_0, %ld_2_1679  %mul4 = fmul double %ld_1_1, %ld_2_1680 681  %add1 = fadd double %mul1, %mul3682  %add2 = fadd double %mul2, %mul4683 684  %add3 = fadd double %add1, %add2685  ret double %add3686}687 688 689; Same as splat_loads() but the splat load has internal uses in the slp graph.690define double @splat_loads_with_internal_uses(ptr %array1, ptr %array2, ptr %ptrA, ptr %ptrB) {691; SSE-LABEL: @splat_loads_with_internal_uses(692; SSE-NEXT:  entry:693; SSE-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY1:%.*]], align 8694; SSE-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAY2:%.*]], align 8695; SSE-NEXT:    [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0>696; SSE-NEXT:    [[TMP3:%.*]] = fmul <2 x double> [[TMP0]], [[TMP2]]697; SSE-NEXT:    [[TMP4:%.*]] = fmul <2 x double> [[TMP0]], [[TMP1]]698; SSE-NEXT:    [[TMP5:%.*]] = fadd <2 x double> [[TMP3]], [[TMP4]]699; SSE-NEXT:    [[TMP6:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> zeroinitializer700; SSE-NEXT:    [[TMP7:%.*]] = fsub <2 x double> [[TMP5]], [[TMP6]]701; SSE-NEXT:    [[TMP8:%.*]] = extractelement <2 x double> [[TMP7]], i32 0702; SSE-NEXT:    [[TMP9:%.*]] = extractelement <2 x double> [[TMP7]], i32 1703; SSE-NEXT:    [[RES:%.*]] = fadd double [[TMP8]], [[TMP9]]704; SSE-NEXT:    ret double [[RES]]705;706; AVX-LABEL: @splat_loads_with_internal_uses(707; AVX-NEXT:  entry:708; AVX-NEXT:    [[GEP_2_1:%.*]] = getelementptr inbounds double, ptr [[ARRAY2:%.*]], i64 1709; AVX-NEXT:    [[LD_2_0:%.*]] = load double, ptr [[ARRAY2]], align 8710; AVX-NEXT:    [[LD_2_1:%.*]] = load double, ptr [[GEP_2_1]], align 8711; AVX-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAY1:%.*]], align 8712; AVX-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> poison, double [[LD_2_0]], i32 0713; AVX-NEXT:    [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> zeroinitializer714; AVX-NEXT:    [[TMP3:%.*]] = fmul <2 x double> [[TMP0]], [[TMP2]]715; AVX-NEXT:    [[TMP4:%.*]] = insertelement <2 x double> poison, double [[LD_2_1]], i32 0716; AVX-NEXT:    [[TMP5:%.*]] = shufflevector <2 x double> [[TMP4]], <2 x double> poison, <2 x i32> zeroinitializer717; AVX-NEXT:    [[TMP6:%.*]] = fmul <2 x double> [[TMP0]], [[TMP5]]718; AVX-NEXT:    [[TMP7:%.*]] = fadd <2 x double> [[TMP3]], [[TMP6]]719; AVX-NEXT:    [[TMP8:%.*]] = fsub <2 x double> [[TMP7]], [[TMP2]]720; AVX-NEXT:    [[TMP9:%.*]] = extractelement <2 x double> [[TMP8]], i32 0721; AVX-NEXT:    [[TMP10:%.*]] = extractelement <2 x double> [[TMP8]], i32 1722; AVX-NEXT:    [[RES:%.*]] = fadd double [[TMP9]], [[TMP10]]723; AVX-NEXT:    ret double [[RES]]724;725entry:726  %gep_1_1 = getelementptr inbounds double, ptr %array1, i64 1727  %ld_1_0 = load double, ptr %array1, align 8728  %ld_1_1 = load double, ptr %gep_1_1, align 8729 730  %gep_2_1 = getelementptr inbounds double, ptr %array2, i64 1731  %ld_2_0 = load double, ptr %array2, align 8732  %ld_2_1 = load double, ptr %gep_2_1, align 8733 734  %mul1 = fmul double %ld_1_0, %ld_2_0735  %mul2 = fmul double %ld_1_1, %ld_2_0736 737  %mul3 = fmul double %ld_1_0, %ld_2_1738  %mul4 = fmul double %ld_1_1, %ld_2_1739 740  %add1 = fadd double %mul1, %mul3741  %add2 = fadd double %mul2, %mul4742 743  ; One more user for the broadcast of %ld_2_0744  %sub1 = fsub double %add1, %ld_2_0745  %sub2 = fsub double %add2, %ld_2_0746 747  %res = fadd double %sub1, %sub2748 749  ret double %res750}751