1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -basic-aa -slp-vectorizer -slp-threshold=-100 -instcombine -dce -S -mtriple=i386-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s 3; RUN: opt < %s -basic-aa -slp-vectorizer -slp-threshold=-100 -instcombine -dce -S -mtriple=i386-apple-macosx10.8.0 -mattr=+sse2 | FileCheck %s --check-prefix=SSE2 4 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 get 8; bigger vectorizable trees. 9 10define void @shuffle_operands1(double * noalias %from, double * noalias %to, double %v1, double %v2) { 11; CHECK-LABEL: @shuffle_operands1( 12; CHECK-NEXT: [[TMP1:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 13; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4 14; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x double> poison, double [[V1:%.*]], i64 0 15; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x double> [[TMP3]], double [[V2:%.*]], i64 1 16; CHECK-NEXT: [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]] 17; CHECK-NEXT: [[TMP6:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 18; CHECK-NEXT: store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4 19; CHECK-NEXT: ret void 20; 21; SSE2-LABEL: @shuffle_operands1( 22; SSE2-NEXT: [[TMP1:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 23; SSE2-NEXT: [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4 24; SSE2-NEXT: [[TMP3:%.*]] = insertelement <2 x double> poison, double [[V1:%.*]], i64 0 25; SSE2-NEXT: [[TMP4:%.*]] = insertelement <2 x double> [[TMP3]], double [[V2:%.*]], i64 1 26; SSE2-NEXT: [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]] 27; SSE2-NEXT: [[TMP6:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 28; SSE2-NEXT: store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4 29; SSE2-NEXT: ret void 30; 31 %from_1 = getelementptr double, double *%from, i64 1 32 %v0_1 = load double , double * %from 33 %v0_2 = load double , double * %from_1 34 %v1_1 = fadd double %v0_1, %v1 35 %v1_2 = fadd double %v2, %v0_2 36 %to_2 = getelementptr double, double * %to, i64 1 37 store double %v1_1, double *%to 38 store double %v1_2, double *%to_2 39 ret void 40} 41 42define void @vecload_vs_broadcast(double * noalias %from, double * noalias %to, double %v1, double %v2) { 43; CHECK-LABEL: @vecload_vs_broadcast( 44; CHECK-NEXT: entry: 45; CHECK-NEXT: br label [[LP:%.*]] 46; CHECK: lp: 47; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 48; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 49; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 50; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0 51; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2> 52; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]] 53; CHECK-NEXT: [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 54; CHECK-NEXT: store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4 55; CHECK-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 56; CHECK: ext: 57; CHECK-NEXT: ret void 58; 59; SSE2-LABEL: @vecload_vs_broadcast( 60; SSE2-NEXT: entry: 61; SSE2-NEXT: br label [[LP:%.*]] 62; SSE2: lp: 63; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 64; SSE2-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 65; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 66; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0 67; SSE2-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2> 68; SSE2-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP1]], [[TMP3]] 69; SSE2-NEXT: [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 70; SSE2-NEXT: store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4 71; SSE2-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 72; SSE2: ext: 73; SSE2-NEXT: ret void 74; 75entry: 76br label %lp 77 78lp: 79 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ] 80 %from_1 = getelementptr double, double *%from, i64 1 81 %v0_1 = load double , double * %from 82 %v0_2 = load double , double * %from_1 83 %v1_1 = fadd double %v0_1, %p 84 %v1_2 = fadd double %v0_1, %v0_2 85 %to_2 = getelementptr double, double * %to, i64 1 86 store double %v1_1, double *%to 87 store double %v1_2, double *%to_2 88br i1 undef, label %lp, label %ext 89 90ext: 91 ret void 92} 93 94define void @vecload_vs_broadcast2(double * noalias %from, double * noalias %to, double %v1, double %v2) { 95; CHECK-LABEL: @vecload_vs_broadcast2( 96; CHECK-NEXT: entry: 97; CHECK-NEXT: br label [[LP:%.*]] 98; CHECK: lp: 99; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 100; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 101; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 102; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0 103; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2> 104; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]] 105; CHECK-NEXT: [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 106; CHECK-NEXT: store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4 107; CHECK-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 108; CHECK: ext: 109; CHECK-NEXT: ret void 110; 111; SSE2-LABEL: @vecload_vs_broadcast2( 112; SSE2-NEXT: entry: 113; SSE2-NEXT: br label [[LP:%.*]] 114; SSE2: lp: 115; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 116; SSE2-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 117; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 118; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0 119; SSE2-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2> 120; SSE2-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]] 121; SSE2-NEXT: [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 122; SSE2-NEXT: store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4 123; SSE2-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 124; SSE2: ext: 125; SSE2-NEXT: ret void 126; 127entry: 128br label %lp 129 130lp: 131 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ] 132 %from_1 = getelementptr double, double *%from, i64 1 133 %v0_1 = load double , double * %from 134 %v0_2 = load double , double * %from_1 135 %v1_1 = fadd double %p, %v0_1 136 %v1_2 = fadd double %v0_2, %v0_1 137 %to_2 = getelementptr double, double * %to, i64 1 138 store double %v1_1, double *%to 139 store double %v1_2, double *%to_2 140br i1 undef, label %lp, label %ext 141 142ext: 143 ret void 144} 145 146define void @vecload_vs_broadcast3(double * noalias %from, double * noalias %to, double %v1, double %v2) { 147; CHECK-LABEL: @vecload_vs_broadcast3( 148; CHECK-NEXT: entry: 149; CHECK-NEXT: br label [[LP:%.*]] 150; CHECK: lp: 151; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 152; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 153; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 154; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0 155; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2> 156; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]] 157; CHECK-NEXT: [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 158; CHECK-NEXT: store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4 159; CHECK-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 160; CHECK: ext: 161; CHECK-NEXT: ret void 162; 163; SSE2-LABEL: @vecload_vs_broadcast3( 164; SSE2-NEXT: entry: 165; SSE2-NEXT: br label [[LP:%.*]] 166; SSE2: lp: 167; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 168; SSE2-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 169; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 170; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> poison, double [[P]], i64 0 171; SSE2-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[TMP2]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2> 172; SSE2-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP3]], [[TMP1]] 173; SSE2-NEXT: [[TMP5:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 174; SSE2-NEXT: store <2 x double> [[TMP4]], <2 x double>* [[TMP5]], align 4 175; SSE2-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 176; SSE2: ext: 177; SSE2-NEXT: ret void 178; 179entry: 180br label %lp 181 182lp: 183 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ] 184 %from_1 = getelementptr double, double *%from, i64 1 185 %v0_1 = load double , double * %from 186 %v0_2 = load double , double * %from_1 187 %v1_1 = fadd double %p, %v0_1 188 %v1_2 = fadd double %v0_1, %v0_2 189 %to_2 = getelementptr double, double * %to, i64 1 190 store double %v1_1, double *%to 191 store double %v1_2, double *%to_2 192br i1 undef, label %lp, label %ext 193 194ext: 195 ret void 196} 197 198define void @shuffle_nodes_match1(double * noalias %from, double * noalias %to, double %v1, double %v2) { 199; CHECK-LABEL: @shuffle_nodes_match1( 200; CHECK-NEXT: entry: 201; CHECK-NEXT: br label [[LP:%.*]] 202; CHECK: lp: 203; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 204; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 205; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 206; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0> 207; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1 208; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]] 209; CHECK-NEXT: [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 210; CHECK-NEXT: store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4 211; CHECK-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 212; CHECK: ext: 213; CHECK-NEXT: ret void 214; 215; SSE2-LABEL: @shuffle_nodes_match1( 216; SSE2-NEXT: entry: 217; SSE2-NEXT: br label [[LP:%.*]] 218; SSE2: lp: 219; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 220; SSE2-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 221; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 222; SSE2-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0> 223; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1 224; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]] 225; SSE2-NEXT: [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 226; SSE2-NEXT: store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4 227; SSE2-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 228; SSE2: ext: 229; SSE2-NEXT: ret void 230; 231entry: 232br label %lp 233 234lp: 235 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ] 236 %from_1 = getelementptr double, double *%from, i64 1 237 %v0_1 = load double , double * %from 238 %v0_2 = load double , double * %from_1 239 %v1_1 = fadd double %v0_2, %v0_1 240 %v1_2 = fadd double %p, %v0_1 241 %to_2 = getelementptr double, double * %to, i64 1 242 store double %v1_1, double *%to 243 store double %v1_2, double *%to_2 244br i1 undef, label %lp, label %ext 245 246ext: 247 ret void 248} 249 250define void @vecload_vs_broadcast4(double * noalias %from, double * noalias %to, double %v1, double %v2) { 251; CHECK-LABEL: @vecload_vs_broadcast4( 252; CHECK-NEXT: entry: 253; CHECK-NEXT: br label [[LP:%.*]] 254; CHECK: lp: 255; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 256; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 257; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 258; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0> 259; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1 260; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]] 261; CHECK-NEXT: [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 262; CHECK-NEXT: store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4 263; CHECK-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 264; CHECK: ext: 265; CHECK-NEXT: ret void 266; 267; SSE2-LABEL: @vecload_vs_broadcast4( 268; SSE2-NEXT: entry: 269; SSE2-NEXT: br label [[LP:%.*]] 270; SSE2: lp: 271; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 272; SSE2-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 273; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 274; SSE2-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0> 275; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1 276; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP2]], [[SHUFFLE]] 277; SSE2-NEXT: [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 278; SSE2-NEXT: store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4 279; SSE2-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 280; SSE2: ext: 281; SSE2-NEXT: ret void 282; 283entry: 284br label %lp 285 286lp: 287 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ] 288 %from_1 = getelementptr double, double *%from, i64 1 289 %v0_1 = load double , double * %from 290 %v0_2 = load double , double * %from_1 291 %v1_1 = fadd double %v0_1, %v0_2 292 %v1_2 = fadd double %p, %v0_1 293 %to_2 = getelementptr double, double * %to, i64 1 294 store double %v1_1, double *%to 295 store double %v1_2, double *%to_2 296br i1 undef, label %lp, label %ext 297 298ext: 299 ret void 300} 301 302 303define void @shuffle_nodes_match2(double * noalias %from, double * noalias %to, double %v1, double %v2) { 304; CHECK-LABEL: @shuffle_nodes_match2( 305; CHECK-NEXT: entry: 306; CHECK-NEXT: br label [[LP:%.*]] 307; CHECK: lp: 308; CHECK-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 309; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 310; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 311; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0> 312; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1 313; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[SHUFFLE]], [[TMP2]] 314; CHECK-NEXT: [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 315; CHECK-NEXT: store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4 316; CHECK-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 317; CHECK: ext: 318; CHECK-NEXT: ret void 319; 320; SSE2-LABEL: @shuffle_nodes_match2( 321; SSE2-NEXT: entry: 322; SSE2-NEXT: br label [[LP:%.*]] 323; SSE2: lp: 324; SSE2-NEXT: [[P:%.*]] = phi double [ 1.000000e+00, [[LP]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 325; SSE2-NEXT: [[TMP0:%.*]] = bitcast double* [[FROM:%.*]] to <2 x double>* 326; SSE2-NEXT: [[TMP1:%.*]] = load <2 x double>, <2 x double>* [[TMP0]], align 4 327; SSE2-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <2 x i32> <i32 1, i32 0> 328; SSE2-NEXT: [[TMP2:%.*]] = insertelement <2 x double> [[TMP1]], double [[P]], i64 1 329; SSE2-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[SHUFFLE]], [[TMP2]] 330; SSE2-NEXT: [[TMP4:%.*]] = bitcast double* [[TO:%.*]] to <2 x double>* 331; SSE2-NEXT: store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 4 332; SSE2-NEXT: br i1 undef, label [[LP]], label [[EXT:%.*]] 333; SSE2: ext: 334; SSE2-NEXT: ret void 335; 336entry: 337br label %lp 338 339lp: 340 %p = phi double [ 1.000000e+00, %lp ], [ 0.000000e+00, %entry ] 341 %from_1 = getelementptr double, double *%from, i64 1 342 %v0_1 = load double , double * %from 343 %v0_2 = load double , double * %from_1 344 %v1_1 = fadd double %v0_1, %v0_2 345 %v1_2 = fadd double %v0_1, %p 346 %to_2 = getelementptr double, double * %to, i64 1 347 store double %v1_1, double *%to 348 store double %v1_2, double *%to_2 349br i1 undef, label %lp, label %ext 350 351ext: 352 ret void 353} 354 355; Make sure we don't scramble operands when we reorder them and destroy 356; 'good' source order. 357 358@a = common global [32000 x float] zeroinitializer, align 16 359 360define void @good_load_order() { 361; CHECK-LABEL: @good_load_order( 362; CHECK-NEXT: entry: 363; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]] 364; CHECK: for.cond1.preheader: 365; CHECK-NEXT: [[TMP0:%.*]] = load float, float* getelementptr inbounds ([32000 x float], [32000 x float]* @a, i32 0, i32 0), align 16 366; CHECK-NEXT: br label [[FOR_BODY3:%.*]] 367; CHECK: for.body3: 368; CHECK-NEXT: [[TMP1:%.*]] = phi float [ [[TMP0]], [[FOR_COND1_PREHEADER]] ], [ [[TMP14:%.*]], [[FOR_BODY3]] ] 369; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY3]] ] 370; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV]] to i32 371; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 372; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP3]] 373; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[INDVARS_IV]] to i32 374; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP4]] 375; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[INDVARS_IV]] to i32 376; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], 4 377; CHECK-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP6]] 378; CHECK-NEXT: [[TMP7:%.*]] = bitcast float* [[ARRAYIDX]] to <4 x float>* 379; CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[TMP7]], align 4 380; CHECK-NEXT: [[TMP9:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0 381; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 5, i32 6> 382; CHECK-NEXT: [[TMP11:%.*]] = fmul <4 x float> [[TMP8]], [[TMP10]] 383; CHECK-NEXT: [[TMP12:%.*]] = bitcast float* [[ARRAYIDX5]] to <4 x float>* 384; CHECK-NEXT: store <4 x float> [[TMP11]], <4 x float>* [[TMP12]], align 4 385; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5 386; CHECK-NEXT: [[TMP13:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 387; CHECK-NEXT: [[ARRAYIDX41:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP13]] 388; CHECK-NEXT: [[TMP14]] = load float, float* [[ARRAYIDX41]], align 4 389; CHECK-NEXT: [[TMP15:%.*]] = extractelement <4 x float> [[TMP8]], i64 3 390; CHECK-NEXT: [[MUL45:%.*]] = fmul float [[TMP14]], [[TMP15]] 391; CHECK-NEXT: store float [[MUL45]], float* [[ARRAYIDX31]], align 4 392; CHECK-NEXT: [[TMP16:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 393; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP16]], 31995 394; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_END:%.*]] 395; CHECK: for.end: 396; CHECK-NEXT: ret void 397; 398; SSE2-LABEL: @good_load_order( 399; SSE2-NEXT: entry: 400; SSE2-NEXT: br label [[FOR_COND1_PREHEADER:%.*]] 401; SSE2: for.cond1.preheader: 402; SSE2-NEXT: [[TMP0:%.*]] = load float, float* getelementptr inbounds ([32000 x float], [32000 x float]* @a, i32 0, i32 0), align 16 403; SSE2-NEXT: br label [[FOR_BODY3:%.*]] 404; SSE2: for.body3: 405; SSE2-NEXT: [[TMP1:%.*]] = phi float [ [[TMP0]], [[FOR_COND1_PREHEADER]] ], [ [[TMP14:%.*]], [[FOR_BODY3]] ] 406; SSE2-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY3]] ] 407; SSE2-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV]] to i32 408; SSE2-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 409; SSE2-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP3]] 410; SSE2-NEXT: [[TMP4:%.*]] = trunc i64 [[INDVARS_IV]] to i32 411; SSE2-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP4]] 412; SSE2-NEXT: [[TMP5:%.*]] = trunc i64 [[INDVARS_IV]] to i32 413; SSE2-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], 4 414; SSE2-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP6]] 415; SSE2-NEXT: [[TMP7:%.*]] = bitcast float* [[ARRAYIDX]] to <4 x float>* 416; SSE2-NEXT: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[TMP7]], align 4 417; SSE2-NEXT: [[TMP9:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0 418; SSE2-NEXT: [[TMP10:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 5, i32 6> 419; SSE2-NEXT: [[TMP11:%.*]] = fmul <4 x float> [[TMP8]], [[TMP10]] 420; SSE2-NEXT: [[TMP12:%.*]] = bitcast float* [[ARRAYIDX5]] to <4 x float>* 421; SSE2-NEXT: store <4 x float> [[TMP11]], <4 x float>* [[TMP12]], align 4 422; SSE2-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 5 423; SSE2-NEXT: [[TMP13:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 424; SSE2-NEXT: [[ARRAYIDX41:%.*]] = getelementptr inbounds [32000 x float], [32000 x float]* @a, i32 0, i32 [[TMP13]] 425; SSE2-NEXT: [[TMP14]] = load float, float* [[ARRAYIDX41]], align 4 426; SSE2-NEXT: [[TMP15:%.*]] = extractelement <4 x float> [[TMP8]], i64 3 427; SSE2-NEXT: [[MUL45:%.*]] = fmul float [[TMP14]], [[TMP15]] 428; SSE2-NEXT: store float [[MUL45]], float* [[ARRAYIDX31]], align 4 429; SSE2-NEXT: [[TMP16:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 430; SSE2-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP16]], 31995 431; SSE2-NEXT: br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_END:%.*]] 432; SSE2: for.end: 433; SSE2-NEXT: ret void 434; 435entry: 436 br label %for.cond1.preheader 437 438for.cond1.preheader: 439 %0 = load float, float* getelementptr inbounds ([32000 x float], [32000 x float]* @a, i64 0, i64 0), align 16 440 br label %for.body3 441 442for.body3: 443 %1 = phi float [ %0, %for.cond1.preheader ], [ %10, %for.body3 ] 444 %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body3 ] 445 %2 = add nsw i64 %indvars.iv, 1 446 %arrayidx = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %2 447 %3 = load float, float* %arrayidx, align 4 448 %arrayidx5 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %indvars.iv 449 %mul6 = fmul float %3, %1 450 store float %mul6, float* %arrayidx5, align 4 451 %4 = add nsw i64 %indvars.iv, 2 452 %arrayidx11 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %4 453 %5 = load float, float* %arrayidx11, align 4 454 %mul15 = fmul float %5, %3 455 store float %mul15, float* %arrayidx, align 4 456 %6 = add nsw i64 %indvars.iv, 3 457 %arrayidx21 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %6 458 %7 = load float, float* %arrayidx21, align 4 459 %mul25 = fmul float %7, %5 460 store float %mul25, float* %arrayidx11, align 4 461 %8 = add nsw i64 %indvars.iv, 4 462 %arrayidx31 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %8 463 %9 = load float, float* %arrayidx31, align 4 464 %mul35 = fmul float %9, %7 465 store float %mul35, float* %arrayidx21, align 4 466 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 5 467 %arrayidx41 = getelementptr inbounds [32000 x float], [32000 x float]* @a, i64 0, i64 %indvars.iv.next 468 %10 = load float, float* %arrayidx41, align 4 469 %mul45 = fmul float %10, %9 470 store float %mul45, float* %arrayidx31, align 4 471 %11 = trunc i64 %indvars.iv.next to i32 472 %cmp2 = icmp slt i32 %11, 31995 473 br i1 %cmp2, label %for.body3, label %for.end 474 475for.end: 476 ret void 477} 478 479; Check vectorization of following code for double data type- 480; c[0] = a[0]+b[0]; 481; c[1] = b[1]+a[1]; // swapped b[1] and a[1] 482 483define void @load_reorder_double(double* nocapture %c, double* noalias nocapture readonly %a, double* noalias nocapture readonly %b){ 484; CHECK-LABEL: @load_reorder_double( 485; CHECK-NEXT: [[TMP1:%.*]] = bitcast double* [[B:%.*]] to <2 x double>* 486; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4 487; CHECK-NEXT: [[TMP3:%.*]] = bitcast double* [[A:%.*]] to <2 x double>* 488; CHECK-NEXT: [[TMP4:%.*]] = load <2 x double>, <2 x double>* [[TMP3]], align 4 489; CHECK-NEXT: [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]] 490; CHECK-NEXT: [[TMP6:%.*]] = bitcast double* [[C:%.*]] to <2 x double>* 491; CHECK-NEXT: store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4 492; CHECK-NEXT: ret void 493; 494; SSE2-LABEL: @load_reorder_double( 495; SSE2-NEXT: [[TMP1:%.*]] = bitcast double* [[B:%.*]] to <2 x double>* 496; SSE2-NEXT: [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 4 497; SSE2-NEXT: [[TMP3:%.*]] = bitcast double* [[A:%.*]] to <2 x double>* 498; SSE2-NEXT: [[TMP4:%.*]] = load <2 x double>, <2 x double>* [[TMP3]], align 4 499; SSE2-NEXT: [[TMP5:%.*]] = fadd <2 x double> [[TMP2]], [[TMP4]] 500; SSE2-NEXT: [[TMP6:%.*]] = bitcast double* [[C:%.*]] to <2 x double>* 501; SSE2-NEXT: store <2 x double> [[TMP5]], <2 x double>* [[TMP6]], align 4 502; SSE2-NEXT: ret void 503; 504 %1 = load double, double* %a 505 %2 = load double, double* %b 506 %3 = fadd double %1, %2 507 store double %3, double* %c 508 %4 = getelementptr inbounds double, double* %b, i64 1 509 %5 = load double, double* %4 510 %6 = getelementptr inbounds double, double* %a, i64 1 511 %7 = load double, double* %6 512 %8 = fadd double %5, %7 513 %9 = getelementptr inbounds double, double* %c, i64 1 514 store double %8, double* %9 515 ret void 516} 517 518; Check vectorization of following code for float data type- 519; c[0] = a[0]+b[0]; 520; c[1] = b[1]+a[1]; // swapped b[1] and a[1] 521; c[2] = a[2]+b[2]; 522; c[3] = a[3]+b[3]; 523 524define void @load_reorder_float(float* nocapture %c, float* noalias nocapture readonly %a, float* noalias nocapture readonly %b){ 525; CHECK-LABEL: @load_reorder_float( 526; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[A:%.*]] to <4 x float>* 527; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4 528; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[B:%.*]] to <4 x float>* 529; CHECK-NEXT: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4 530; CHECK-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]] 531; CHECK-NEXT: [[TMP6:%.*]] = bitcast float* [[C:%.*]] to <4 x float>* 532; CHECK-NEXT: store <4 x float> [[TMP5]], <4 x float>* [[TMP6]], align 4 533; CHECK-NEXT: ret void 534; 535; SSE2-LABEL: @load_reorder_float( 536; SSE2-NEXT: [[TMP1:%.*]] = bitcast float* [[A:%.*]] to <4 x float>* 537; SSE2-NEXT: [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4 538; SSE2-NEXT: [[TMP3:%.*]] = bitcast float* [[B:%.*]] to <4 x float>* 539; SSE2-NEXT: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4 540; SSE2-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]] 541; SSE2-NEXT: [[TMP6:%.*]] = bitcast float* [[C:%.*]] to <4 x float>* 542; SSE2-NEXT: store <4 x float> [[TMP5]], <4 x float>* [[TMP6]], align 4 543; SSE2-NEXT: ret void 544; 545 %1 = load float, float* %a 546 %2 = load float, float* %b 547 %3 = fadd float %1, %2 548 store float %3, float* %c 549 %4 = getelementptr inbounds float, float* %b, i64 1 550 %5 = load float, float* %4 551 %6 = getelementptr inbounds float, float* %a, i64 1 552 %7 = load float, float* %6 553 %8 = fadd float %5, %7 554 %9 = getelementptr inbounds float, float* %c, i64 1 555 store float %8, float* %9 556 %10 = getelementptr inbounds float, float* %a, i64 2 557 %11 = load float, float* %10 558 %12 = getelementptr inbounds float, float* %b, i64 2 559 %13 = load float, float* %12 560 %14 = fadd float %11, %13 561 %15 = getelementptr inbounds float, float* %c, i64 2 562 store float %14, float* %15 563 %16 = getelementptr inbounds float, float* %a, i64 3 564 %17 = load float, float* %16 565 %18 = getelementptr inbounds float, float* %b, i64 3 566 %19 = load float, float* %18 567 %20 = fadd float %17, %19 568 %21 = getelementptr inbounds float, float* %c, i64 3 569 store float %20, float* %21 570 ret void 571} 572 573; Check we properly reorder the below code so that it gets vectorized optimally- 574; a[0] = (b[0]+c[0])+d[0]; 575; a[1] = d[1]+(b[1]+c[1]); 576; a[2] = (b[2]+c[2])+d[2]; 577; a[3] = (b[3]+c[3])+d[3]; 578 579define void @opcode_reorder(float* noalias nocapture %a, float* noalias nocapture readonly %b, float* noalias nocapture readonly %c,float* noalias nocapture readonly %d) { 580; CHECK-LABEL: @opcode_reorder( 581; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[B:%.*]] to <4 x float>* 582; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4 583; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[C:%.*]] to <4 x float>* 584; CHECK-NEXT: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4 585; CHECK-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]] 586; CHECK-NEXT: [[TMP6:%.*]] = bitcast float* [[D:%.*]] to <4 x float>* 587; CHECK-NEXT: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[TMP6]], align 4 588; CHECK-NEXT: [[TMP8:%.*]] = fadd <4 x float> [[TMP7]], [[TMP5]] 589; CHECK-NEXT: [[TMP9:%.*]] = bitcast float* [[A:%.*]] to <4 x float>* 590; CHECK-NEXT: store <4 x float> [[TMP8]], <4 x float>* [[TMP9]], align 4 591; CHECK-NEXT: ret void 592; 593; SSE2-LABEL: @opcode_reorder( 594; SSE2-NEXT: [[TMP1:%.*]] = bitcast float* [[B:%.*]] to <4 x float>* 595; SSE2-NEXT: [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4 596; SSE2-NEXT: [[TMP3:%.*]] = bitcast float* [[C:%.*]] to <4 x float>* 597; SSE2-NEXT: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4 598; SSE2-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP2]], [[TMP4]] 599; SSE2-NEXT: [[TMP6:%.*]] = bitcast float* [[D:%.*]] to <4 x float>* 600; SSE2-NEXT: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[TMP6]], align 4 601; SSE2-NEXT: [[TMP8:%.*]] = fadd <4 x float> [[TMP7]], [[TMP5]] 602; SSE2-NEXT: [[TMP9:%.*]] = bitcast float* [[A:%.*]] to <4 x float>* 603; SSE2-NEXT: store <4 x float> [[TMP8]], <4 x float>* [[TMP9]], align 4 604; SSE2-NEXT: ret void 605; 606 %1 = load float, float* %b 607 %2 = load float, float* %c 608 %3 = fadd float %1, %2 609 %4 = load float, float* %d 610 %5 = fadd float %3, %4 611 store float %5, float* %a 612 %6 = getelementptr inbounds float, float* %d, i64 1 613 %7 = load float, float* %6 614 %8 = getelementptr inbounds float, float* %b, i64 1 615 %9 = load float, float* %8 616 %10 = getelementptr inbounds float, float* %c, i64 1 617 %11 = load float, float* %10 618 %12 = fadd float %9, %11 619 %13 = fadd float %7, %12 620 %14 = getelementptr inbounds float, float* %a, i64 1 621 store float %13, float* %14 622 %15 = getelementptr inbounds float, float* %b, i64 2 623 %16 = load float, float* %15 624 %17 = getelementptr inbounds float, float* %c, i64 2 625 %18 = load float, float* %17 626 %19 = fadd float %16, %18 627 %20 = getelementptr inbounds float, float* %d, i64 2 628 %21 = load float, float* %20 629 %22 = fadd float %19, %21 630 %23 = getelementptr inbounds float, float* %a, i64 2 631 store float %22, float* %23 632 %24 = getelementptr inbounds float, float* %b, i64 3 633 %25 = load float, float* %24 634 %26 = getelementptr inbounds float, float* %c, i64 3 635 %27 = load float, float* %26 636 %28 = fadd float %25, %27 637 %29 = getelementptr inbounds float, float* %d, i64 3 638 %30 = load float, float* %29 639 %31 = fadd float %28, %30 640 %32 = getelementptr inbounds float, float* %a, i64 3 641 store float %31, float* %32 642 ret void 643} 644