594 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=slp-vectorizer,dce -slp-threshold=-100 -S -mtriple=i386-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s3; RUN: opt < %s -passes=slp-vectorizer,dce -slp-threshold=-100 -S -mtriple=i386-apple-macosx10.8.0 -mattr=+sse2 | FileCheck %s --check-prefix=SSE24 5target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128"6 7; Make sure we order the operands of commutative operations so that we get8; bigger vectorizable trees.9 10define void @shuffle_operands1(ptr noalias %from, ptr noalias %to, double %v1, double %v2) {11; CHECK-LABEL: @shuffle_operands1(12; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 413; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V1:%.*]], i32 014; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[V2:%.*]], i32 115; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]]16; CHECK-NEXT: store <2 x double> [[TMP4]], ptr [[TO:%.*]], align 417; CHECK-NEXT: ret void18;19; SSE2-LABEL: @shuffle_operands1(20; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 421; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V1:%.*]], i32 022; SSE2-NEXT: [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[V2:%.*]], i32 123; SSE2-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]]24; SSE2-NEXT: store <2 x double> [[TMP4]], ptr [[TO:%.*]], align 425; SSE2-NEXT: ret void26;27 %from_1 = getelementptr double, ptr %from, i64 128 %v0_1 = load double , ptr %from29 %v0_2 = load double , ptr %from_130 %v1_1 = fadd double %v0_1, %v131 %v1_2 = fadd double %v2, %v0_232 %to_2 = getelementptr double, ptr %to, i64 133 store double %v1_1, ptr %to34 store double %v1_2, ptr %to_235 ret void36}37 38define void @vecload_vs_broadcast(ptr noalias %from, ptr noalias %to, double %v1, double %v2, i1 %c) {39; CHECK-LABEL: @vecload_vs_broadcast(40; CHECK-NEXT: entry:41; CHECK-NEXT: br label [[LP:%.*]]42; CHECK: lp:43; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]44; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 445; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>46; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i32 047; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP0]], [[TMP2]]48; CHECK-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 449; CHECK-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]50; CHECK: ext:51; CHECK-NEXT: ret void52;53; SSE2-LABEL: @vecload_vs_broadcast(54; SSE2-NEXT: entry:55; SSE2-NEXT: br label [[LP:%.*]]56; SSE2: lp:57; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]58; SSE2-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 459; SSE2-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>60; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i32 061; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP0]], [[TMP2]]62; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 463; SSE2-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]64; SSE2: ext:65; SSE2-NEXT: ret void66;67entry:68br label %lp69 70lp:71 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]72 %from_1 = getelementptr double, ptr %from, i64 173 %v0_1 = load double , ptr %from74 %v0_2 = load double , ptr %from_175 %v1_1 = fadd double %v0_1, %p76 %v1_2 = fadd double %v0_1, %v0_277 %to_2 = getelementptr double, ptr %to, i64 178 store double %v1_1, ptr %to79 store double %v1_2, ptr %to_280 br i1 %c, label %lp, label %ext81 82ext:83 ret void84}85 86define void @vecload_vs_broadcast2(ptr noalias %from, ptr noalias %to, double %v1, double %v2, i1 %c) {87; CHECK-LABEL: @vecload_vs_broadcast2(88; CHECK-NEXT: entry:89; CHECK-NEXT: br label [[LP:%.*]]90; CHECK: lp:91; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]92; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 493; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>94; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i32 095; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP0]]96; CHECK-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 497; CHECK-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]98; CHECK: ext:99; CHECK-NEXT: ret void100;101; SSE2-LABEL: @vecload_vs_broadcast2(102; SSE2-NEXT: entry:103; SSE2-NEXT: br label [[LP:%.*]]104; SSE2: lp:105; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]106; SSE2-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4107; SSE2-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>108; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i32 0109; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP0]]110; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4111; SSE2-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]112; SSE2: ext:113; SSE2-NEXT: ret void114;115entry:116br label %lp117 118lp:119 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]120 %from_1 = getelementptr double, ptr %from, i64 1121 %v0_1 = load double , ptr %from122 %v0_2 = load double , ptr %from_1123 %v1_1 = fadd double %p, %v0_1124 %v1_2 = fadd double %v0_2, %v0_1125 %to_2 = getelementptr double, ptr %to, i64 1126 store double %v1_1, ptr %to127 store double %v1_2, ptr %to_2128 br i1 %c, label %lp, label %ext129 130ext:131 ret void132}133 134define void @vecload_vs_broadcast3(ptr noalias %from, ptr noalias %to, double %v1, double %v2, i1 %c) {135; CHECK-LABEL: @vecload_vs_broadcast3(136; CHECK-NEXT: entry:137; CHECK-NEXT: br label [[LP:%.*]]138; CHECK: lp:139; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]140; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4141; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>142; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i32 0143; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP0]]144; CHECK-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4145; CHECK-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]146; CHECK: ext:147; CHECK-NEXT: ret void148;149; SSE2-LABEL: @vecload_vs_broadcast3(150; SSE2-NEXT: entry:151; SSE2-NEXT: br label [[LP:%.*]]152; SSE2: lp:153; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]154; SSE2-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4155; SSE2-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>156; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i32 0157; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP0]]158; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4159; SSE2-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]160; SSE2: ext:161; SSE2-NEXT: ret void162;163entry:164br label %lp165 166lp:167 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]168 %from_1 = getelementptr double, ptr %from, i64 1169 %v0_1 = load double , ptr %from170 %v0_2 = load double , ptr %from_1171 %v1_1 = fadd double %p, %v0_1172 %v1_2 = fadd double %v0_1, %v0_2173 %to_2 = getelementptr double, ptr %to, i64 1174 store double %v1_1, ptr %to175 store double %v1_2, ptr %to_2176 br i1 %c, label %lp, label %ext177 178ext:179 ret void180}181 182define void @shuffle_nodes_match1(ptr noalias %from, ptr noalias %to, double %v1, double %v2, i1 %c) {183; CHECK-LABEL: @shuffle_nodes_match1(184; CHECK-NEXT: entry:185; CHECK-NEXT: br label [[LP:%.*]]186; CHECK: lp:187; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]188; CHECK-NEXT: [[FROM_1:%.*]] = getelementptr double, ptr [[FROM:%.*]], i64 1189; CHECK-NEXT: [[V0_1:%.*]] = load double, ptr [[FROM]], align 4190; CHECK-NEXT: [[V0_2:%.*]] = load double, ptr [[FROM_1]], align 4191; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V0_2]], i32 0192; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[P]], i32 1193; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V0_1]], i32 0194; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> poison, <2 x i32> zeroinitializer195; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]]196; CHECK-NEXT: store <2 x double> [[TMP4]], ptr [[TO:%.*]], align 4197; CHECK-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]198; CHECK: ext:199; CHECK-NEXT: ret void200;201; SSE2-LABEL: @shuffle_nodes_match1(202; SSE2-NEXT: entry:203; SSE2-NEXT: br label [[LP:%.*]]204; SSE2: lp:205; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]206; SSE2-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4207; SSE2-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 1, i32 0>208; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP0]], double [[P]], i32 1209; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP1]]210; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4211; SSE2-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]212; SSE2: ext:213; SSE2-NEXT: ret void214;215entry:216br label %lp217 218lp:219 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]220 %from_1 = getelementptr double, ptr %from, i64 1221 %v0_1 = load double , ptr %from222 %v0_2 = load double , ptr %from_1223 %v1_1 = fadd double %v0_2, %v0_1224 %v1_2 = fadd double %p, %v0_1225 %to_2 = getelementptr double, ptr %to, i64 1226 store double %v1_1, ptr %to227 store double %v1_2, ptr %to_2228 br i1 %c, label %lp, label %ext229 230ext:231 ret void232}233 234define void @vecload_vs_broadcast4(ptr noalias %from, ptr noalias %to, double %v1, double %v2, i1 %c) {235; CHECK-LABEL: @vecload_vs_broadcast4(236; CHECK-NEXT: entry:237; CHECK-NEXT: br label [[LP:%.*]]238; CHECK: lp:239; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]240; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4241; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 1, i32 0>242; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP0]], double [[P]], i32 1243; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP1]]244; CHECK-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4245; CHECK-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]246; CHECK: ext:247; CHECK-NEXT: ret void248;249; SSE2-LABEL: @vecload_vs_broadcast4(250; SSE2-NEXT: entry:251; SSE2-NEXT: br label [[LP:%.*]]252; SSE2: lp:253; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]254; SSE2-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4255; SSE2-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 1, i32 0>256; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP0]], double [[P]], i32 1257; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[TMP1]]258; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4259; SSE2-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]260; SSE2: ext:261; SSE2-NEXT: ret void262;263entry:264br label %lp265 266lp:267 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]268 %from_1 = getelementptr double, ptr %from, i64 1269 %v0_1 = load double , ptr %from270 %v0_2 = load double , ptr %from_1271 %v1_1 = fadd double %v0_1, %v0_2272 %v1_2 = fadd double %p, %v0_1273 %to_2 = getelementptr double, ptr %to, i64 1274 store double %v1_1, ptr %to275 store double %v1_2, ptr %to_2276 br i1 %c, label %lp, label %ext277 278ext:279 ret void280}281 282 283define void @shuffle_nodes_match2(ptr noalias %from, ptr noalias %to, double %v1, double %v2, i1 %c) {284; CHECK-LABEL: @shuffle_nodes_match2(285; CHECK-NEXT: entry:286; CHECK-NEXT: br label [[LP:%.*]]287; CHECK: lp:288; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]289; CHECK-NEXT: [[FROM_1:%.*]] = getelementptr double, ptr [[FROM:%.*]], i64 1290; CHECK-NEXT: [[V0_1:%.*]] = load double, ptr [[FROM]], align 4291; CHECK-NEXT: [[V0_2:%.*]] = load double, ptr [[FROM_1]], align 4292; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x double> poison, double [[V0_1]], i32 0293; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> zeroinitializer294; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[V0_2]], i32 0295; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x double> [[TMP2]], double [[P]], i32 1296; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]]297; CHECK-NEXT: store <2 x double> [[TMP4]], ptr [[TO:%.*]], align 4298; CHECK-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]299; CHECK: ext:300; CHECK-NEXT: ret void301;302; SSE2-LABEL: @shuffle_nodes_match2(303; SSE2-NEXT: entry:304; SSE2-NEXT: br label [[LP:%.*]]305; SSE2: lp:306; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]307; SSE2-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[FROM:%.*]], align 4308; SSE2-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> poison, <2 x i32> <i32 1, i32 0>309; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP0]], double [[P]], i32 1310; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP1]], [[TMP2]]311; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[TO:%.*]], align 4312; SSE2-NEXT: br i1 [[C:%.*]], label [[LP]], label [[EXT:%.*]]313; SSE2: ext:314; SSE2-NEXT: ret void315;316entry:317br label %lp318 319lp:320 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ]321 %from_1 = getelementptr double, ptr %from, i64 1322 %v0_1 = load double , ptr %from323 %v0_2 = load double , ptr %from_1324 %v1_1 = fadd double %v0_1, %v0_2325 %v1_2 = fadd double %v0_1, %p326 %to_2 = getelementptr double, ptr %to, i64 1327 store double %v1_1, ptr %to328 store double %v1_2, ptr %to_2329 br i1 %c, label %lp, label %ext330 331ext:332 ret void333}334 335; Make sure we don't scramble operands when we reorder them and destroy336; 'good' source order.337 338@a = common global [32000 x float] zeroinitializer, align 16339 340define void @good_load_order() {341; CHECK-LABEL: @good_load_order(342; CHECK-NEXT: entry:343; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]]344; CHECK: for.cond1.preheader:345; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr @a, align 16346; CHECK-NEXT: br label [[FOR_BODY3:%.*]]347; CHECK: for.body3:348; CHECK-NEXT: [[TMP1:%.*]] = phi float [ [[TMP0]], [[FOR_COND1_PREHEADER]] ], [ [[TMP13:%.*]], [[FOR_BODY3]] ]349; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY3]] ]350; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[INDVARS_IV]], 1351; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[TMP2]]352; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[INDVARS_IV]]353; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], 4354; CHECK-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[TMP3]]355; CHECK-NEXT: [[TMP7:%.*]] = load float, ptr [[ARRAYIDX31]], align 4356; CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 4357; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x float> [[TMP8]], <4 x float> poison, <4 x i32> <i32 poison, i32 0, i32 1, i32 2>358; CHECK-NEXT: [[TMP12:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i32 0359; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP12]], <4 x i32> <i32 4, i32 1, i32 2, i32 3>360; CHECK-NEXT: [[TMP11:%.*]] = fmul <4 x float> [[TMP8]], [[TMP10]]361; CHECK-NEXT: store <4 x float> [[TMP11]], ptr [[ARRAYIDX5]], align 4362; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5363; CHECK-NEXT: [[ARRAYIDX41:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[INDVARS_IV_NEXT]]364; CHECK-NEXT: [[TMP13]] = load float, ptr [[ARRAYIDX41]], align 4365; CHECK-NEXT: [[MUL45:%.*]] = fmul float [[TMP13]], [[TMP7]]366; CHECK-NEXT: store float [[MUL45]], ptr [[ARRAYIDX31]], align 4367; CHECK-NEXT: [[TMP14:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32368; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP14]], 31995369; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_END:%.*]]370; CHECK: for.end:371; CHECK-NEXT: ret void372;373; SSE2-LABEL: @good_load_order(374; SSE2-NEXT: entry:375; SSE2-NEXT: br label [[FOR_COND1_PREHEADER:%.*]]376; SSE2: for.cond1.preheader:377; SSE2-NEXT: [[TMP0:%.*]] = load float, ptr @a, align 16378; SSE2-NEXT: br label [[FOR_BODY3:%.*]]379; SSE2: for.body3:380; SSE2-NEXT: [[TMP1:%.*]] = phi float [ [[TMP0]], [[FOR_COND1_PREHEADER]] ], [ [[TMP13:%.*]], [[FOR_BODY3]] ]381; SSE2-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY3]] ]382; SSE2-NEXT: [[TMP2:%.*]] = add nsw i64 [[INDVARS_IV]], 1383; SSE2-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[TMP2]]384; SSE2-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[INDVARS_IV]]385; SSE2-NEXT: [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], 4386; SSE2-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[TMP3]]387; SSE2-NEXT: [[TMP7:%.*]] = load float, ptr [[ARRAYIDX31]], align 4388; SSE2-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 4389; SSE2-NEXT: [[TMP9:%.*]] = shufflevector <4 x float> [[TMP8]], <4 x float> poison, <4 x i32> <i32 poison, i32 0, i32 1, i32 2>390; SSE2-NEXT: [[TMP12:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i32 0391; SSE2-NEXT: [[TMP10:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP12]], <4 x i32> <i32 4, i32 1, i32 2, i32 3>392; SSE2-NEXT: [[TMP11:%.*]] = fmul <4 x float> [[TMP8]], [[TMP10]]393; SSE2-NEXT: store <4 x float> [[TMP11]], ptr [[ARRAYIDX5]], align 4394; SSE2-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5395; SSE2-NEXT: [[ARRAYIDX41:%.*]] = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 [[INDVARS_IV_NEXT]]396; SSE2-NEXT: [[TMP13]] = load float, ptr [[ARRAYIDX41]], align 4397; SSE2-NEXT: [[MUL45:%.*]] = fmul float [[TMP13]], [[TMP7]]398; SSE2-NEXT: store float [[MUL45]], ptr [[ARRAYIDX31]], align 4399; SSE2-NEXT: [[TMP14:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32400; SSE2-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP14]], 31995401; SSE2-NEXT: br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_END:%.*]]402; SSE2: for.end:403; SSE2-NEXT: ret void404;405entry:406 br label %for.cond1.preheader407 408for.cond1.preheader:409 %0 = load float, ptr @a, align 16410 br label %for.body3411 412for.body3:413 %1 = phi float [ %0, %for.cond1.preheader ], [ %10, %for.body3 ]414 %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body3 ]415 %2 = add nsw i64 %indvars.iv, 1416 %arrayidx = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 %2417 %3 = load float, ptr %arrayidx, align 4418 %arrayidx5 = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 %indvars.iv419 %mul6 = fmul float %3, %1420 store float %mul6, ptr %arrayidx5, align 4421 %4 = add nsw i64 %indvars.iv, 2422 %arrayidx11 = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 %4423 %5 = load float, ptr %arrayidx11, align 4424 %mul15 = fmul float %5, %3425 store float %mul15, ptr %arrayidx, align 4426 %6 = add nsw i64 %indvars.iv, 3427 %arrayidx21 = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 %6428 %7 = load float, ptr %arrayidx21, align 4429 %mul25 = fmul float %7, %5430 store float %mul25, ptr %arrayidx11, align 4431 %8 = add nsw i64 %indvars.iv, 4432 %arrayidx31 = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 %8433 %9 = load float, ptr %arrayidx31, align 4434 %mul35 = fmul float %9, %7435 store float %mul35, ptr %arrayidx21, align 4436 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 5437 %arrayidx41 = getelementptr inbounds [32000 x float], ptr @a, i64 0, i64 %indvars.iv.next438 %10 = load float, ptr %arrayidx41, align 4439 %mul45 = fmul float %10, %9440 store float %mul45, ptr %arrayidx31, align 4441 %11 = trunc i64 %indvars.iv.next to i32442 %cmp2 = icmp slt i32 %11, 31995443 br i1 %cmp2, label %for.body3, label %for.end444 445for.end:446 ret void447}448 449; Check vectorization of following code for double data type-450; c[0] = a[0]+b[0];451; c[1] = b[1]+a[1]; // swapped b[1] and a[1]452 453define void @load_reorder_double(ptr nocapture %c, ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b){454; CHECK-LABEL: @load_reorder_double(455; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B:%.*]], align 4456; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 4457; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP1]], [[TMP2]]458; CHECK-NEXT: store <2 x double> [[TMP3]], ptr [[C:%.*]], align 4459; CHECK-NEXT: ret void460;461; SSE2-LABEL: @load_reorder_double(462; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B:%.*]], align 4463; SSE2-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 4464; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP1]], [[TMP2]]465; SSE2-NEXT: store <2 x double> [[TMP3]], ptr [[C:%.*]], align 4466; SSE2-NEXT: ret void467;468 %1 = load double, ptr %a469 %2 = load double, ptr %b470 %3 = fadd double %1, %2471 store double %3, ptr %c472 %4 = getelementptr inbounds double, ptr %b, i64 1473 %5 = load double, ptr %4474 %6 = getelementptr inbounds double, ptr %a, i64 1475 %7 = load double, ptr %6476 %8 = fadd double %5, %7477 %9 = getelementptr inbounds double, ptr %c, i64 1478 store double %8, ptr %9479 ret void480}481 482; Check vectorization of following code for float data type-483; c[0] = a[0]+b[0];484; c[1] = b[1]+a[1]; // swapped b[1] and a[1]485; c[2] = a[2]+b[2];486; c[3] = a[3]+b[3];487 488define void @load_reorder_float(ptr nocapture %c, ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b){489; CHECK-LABEL: @load_reorder_float(490; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[A:%.*]], align 4491; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[B:%.*]], align 4492; CHECK-NEXT: [[TMP3:%.*]] = fadd <4 x float> [[TMP1]], [[TMP2]]493; CHECK-NEXT: store <4 x float> [[TMP3]], ptr [[C:%.*]], align 4494; CHECK-NEXT: ret void495;496; SSE2-LABEL: @load_reorder_float(497; SSE2-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[A:%.*]], align 4498; SSE2-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[B:%.*]], align 4499; SSE2-NEXT: [[TMP3:%.*]] = fadd <4 x float> [[TMP1]], [[TMP2]]500; SSE2-NEXT: store <4 x float> [[TMP3]], ptr [[C:%.*]], align 4501; SSE2-NEXT: ret void502;503 %1 = load float, ptr %a504 %2 = load float, ptr %b505 %3 = fadd float %1, %2506 store float %3, ptr %c507 %4 = getelementptr inbounds float, ptr %b, i64 1508 %5 = load float, ptr %4509 %6 = getelementptr inbounds float, ptr %a, i64 1510 %7 = load float, ptr %6511 %8 = fadd float %5, %7512 %9 = getelementptr inbounds float, ptr %c, i64 1513 store float %8, ptr %9514 %10 = getelementptr inbounds float, ptr %a, i64 2515 %11 = load float, ptr %10516 %12 = getelementptr inbounds float, ptr %b, i64 2517 %13 = load float, ptr %12518 %14 = fadd float %11, %13519 %15 = getelementptr inbounds float, ptr %c, i64 2520 store float %14, ptr %15521 %16 = getelementptr inbounds float, ptr %a, i64 3522 %17 = load float, ptr %16523 %18 = getelementptr inbounds float, ptr %b, i64 3524 %19 = load float, ptr %18525 %20 = fadd float %17, %19526 %21 = getelementptr inbounds float, ptr %c, i64 3527 store float %20, ptr %21528 ret void529}530 531; Check we properly reorder the below code so that it gets vectorized optimally-532; a[0] = (b[0]+c[0])+d[0];533; a[1] = d[1]+(b[1]+c[1]);534; a[2] = (b[2]+c[2])+d[2];535; a[3] = (b[3]+c[3])+d[3];536 537define void @opcode_reorder(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr noalias nocapture readonly %c,ptr noalias nocapture readonly %d) {538; CHECK-LABEL: @opcode_reorder(539; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B:%.*]], align 4540; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[C:%.*]], align 4541; CHECK-NEXT: [[TMP3:%.*]] = fadd <4 x float> [[TMP1]], [[TMP2]]542; CHECK-NEXT: [[TMP4:%.*]] = load <4 x float>, ptr [[D:%.*]], align 4543; CHECK-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP4]], [[TMP3]]544; CHECK-NEXT: store <4 x float> [[TMP5]], ptr [[A:%.*]], align 4545; CHECK-NEXT: ret void546;547; SSE2-LABEL: @opcode_reorder(548; SSE2-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B:%.*]], align 4549; SSE2-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[C:%.*]], align 4550; SSE2-NEXT: [[TMP3:%.*]] = fadd <4 x float> [[TMP1]], [[TMP2]]551; SSE2-NEXT: [[TMP4:%.*]] = load <4 x float>, ptr [[D:%.*]], align 4552; SSE2-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP4]], [[TMP3]]553; SSE2-NEXT: store <4 x float> [[TMP5]], ptr [[A:%.*]], align 4554; SSE2-NEXT: ret void555;556 %1 = load float, ptr %b557 %2 = load float, ptr %c558 %3 = fadd float %1, %2559 %4 = load float, ptr %d560 %5 = fadd float %3, %4561 store float %5, ptr %a562 %6 = getelementptr inbounds float, ptr %d, i64 1563 %7 = load float, ptr %6564 %8 = getelementptr inbounds float, ptr %b, i64 1565 %9 = load float, ptr %8566 %10 = getelementptr inbounds float, ptr %c, i64 1567 %11 = load float, ptr %10568 %12 = fadd float %9, %11569 %13 = fadd float %7, %12570 %14 = getelementptr inbounds float, ptr %a, i64 1571 store float %13, ptr %14572 %15 = getelementptr inbounds float, ptr %b, i64 2573 %16 = load float, ptr %15574 %17 = getelementptr inbounds float, ptr %c, i64 2575 %18 = load float, ptr %17576 %19 = fadd float %16, %18577 %20 = getelementptr inbounds float, ptr %d, i64 2578 %21 = load float, ptr %20579 %22 = fadd float %19, %21580 %23 = getelementptr inbounds float, ptr %a, i64 2581 store float %22, ptr %23582 %24 = getelementptr inbounds float, ptr %b, i64 3583 %25 = load float, ptr %24584 %26 = getelementptr inbounds float, ptr %c, i64 3585 %27 = load float, ptr %26586 %28 = fadd float %25, %27587 %29 = getelementptr inbounds float, ptr %d, i64 3588 %30 = load float, ptr %29589 %31 = fadd float %28, %30590 %32 = getelementptr inbounds float, ptr %a, i64 3591 store float %31, ptr %32592 ret void593}594