; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -basic-aa -loop-vectorize < %s | FileCheck %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" ; Function Attrs: nounwind define void @foo(double* noalias nocapture %a, double* noalias nocapture readonly %b) #0 { ; CHECK-LABEL: @foo( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 2 ; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 6 ; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 8 ; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDEX]], 10 ; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 12 ; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[INDEX]], 14 ; CHECK-NEXT: [[TMP8:%.*]] = shl nsw i64 [[TMP0]], 1 ; CHECK-NEXT: [[TMP9:%.*]] = shl nsw i64 [[TMP1]], 1 ; CHECK-NEXT: [[TMP10:%.*]] = shl nsw i64 [[TMP2]], 1 ; CHECK-NEXT: [[TMP11:%.*]] = shl nsw i64 [[TMP3]], 1 ; CHECK-NEXT: [[TMP12:%.*]] = shl nsw i64 [[TMP4]], 1 ; CHECK-NEXT: [[TMP13:%.*]] = shl nsw i64 [[TMP5]], 1 ; CHECK-NEXT: [[TMP14:%.*]] = shl nsw i64 [[TMP6]], 1 ; CHECK-NEXT: [[TMP15:%.*]] = shl nsw i64 [[TMP7]], 1 ; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds double, double* [[B:%.*]], i64 [[TMP8]] ; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP9]] ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP10]] ; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP11]] ; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP12]] ; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP13]] ; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP14]] ; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP15]] ; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds double, double* [[TMP16]], i32 0 ; CHECK-NEXT: [[TMP25:%.*]] = bitcast double* [[TMP24]] to <4 x double>* ; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds double, double* [[TMP17]], i32 0 ; CHECK-NEXT: [[TMP27:%.*]] = bitcast double* [[TMP26]] to <4 x double>* ; CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds double, double* [[TMP18]], i32 0 ; CHECK-NEXT: [[TMP29:%.*]] = bitcast double* [[TMP28]] to <4 x double>* ; CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds double, double* [[TMP19]], i32 0 ; CHECK-NEXT: [[TMP31:%.*]] = bitcast double* [[TMP30]] to <4 x double>* ; CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds double, double* [[TMP20]], i32 0 ; CHECK-NEXT: [[TMP33:%.*]] = bitcast double* [[TMP32]] to <4 x double>* ; CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds double, double* [[TMP21]], i32 0 ; CHECK-NEXT: [[TMP35:%.*]] = bitcast double* [[TMP34]] to <4 x double>* ; CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds double, double* [[TMP22]], i32 0 ; CHECK-NEXT: [[TMP37:%.*]] = bitcast double* [[TMP36]] to <4 x double>* ; CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds double, double* [[TMP23]], i32 0 ; CHECK-NEXT: [[TMP39:%.*]] = bitcast double* [[TMP38]] to <4 x double>* ; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <4 x double>, <4 x double>* [[TMP25]], align 8 ; CHECK-NEXT: [[WIDE_VEC1:%.*]] = load <4 x double>, <4 x double>* [[TMP27]], align 8 ; CHECK-NEXT: [[WIDE_VEC2:%.*]] = load <4 x double>, <4 x double>* [[TMP29]], align 8 ; CHECK-NEXT: [[WIDE_VEC3:%.*]] = load <4 x double>, <4 x double>* [[TMP31]], align 8 ; CHECK-NEXT: [[WIDE_VEC4:%.*]] = load <4 x double>, <4 x double>* [[TMP33]], align 8 ; CHECK-NEXT: [[WIDE_VEC5:%.*]] = load <4 x double>, <4 x double>* [[TMP35]], align 8 ; CHECK-NEXT: [[WIDE_VEC6:%.*]] = load <4 x double>, <4 x double>* [[TMP37]], align 8 ; CHECK-NEXT: [[WIDE_VEC7:%.*]] = load <4 x double>, <4 x double>* [[TMP39]], align 8 ; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <4 x double> [[WIDE_VEC]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC8:%.*]] = shufflevector <4 x double> [[WIDE_VEC1]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC9:%.*]] = shufflevector <4 x double> [[WIDE_VEC2]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC10:%.*]] = shufflevector <4 x double> [[WIDE_VEC3]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC11:%.*]] = shufflevector <4 x double> [[WIDE_VEC4]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC12:%.*]] = shufflevector <4 x double> [[WIDE_VEC5]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC13:%.*]] = shufflevector <4 x double> [[WIDE_VEC6]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC14:%.*]] = shufflevector <4 x double> [[WIDE_VEC7]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC15:%.*]] = shufflevector <4 x double> [[WIDE_VEC]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC16:%.*]] = shufflevector <4 x double> [[WIDE_VEC1]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC17:%.*]] = shufflevector <4 x double> [[WIDE_VEC2]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC18:%.*]] = shufflevector <4 x double> [[WIDE_VEC3]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC19:%.*]] = shufflevector <4 x double> [[WIDE_VEC4]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC20:%.*]] = shufflevector <4 x double> [[WIDE_VEC5]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC21:%.*]] = shufflevector <4 x double> [[WIDE_VEC6]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC22:%.*]] = shufflevector <4 x double> [[WIDE_VEC7]], <4 x double> poison, <2 x i32> ; CHECK-NEXT: [[TMP40:%.*]] = fadd <2 x double> [[STRIDED_VEC]], [[STRIDED_VEC15]] ; CHECK-NEXT: [[TMP41:%.*]] = fadd <2 x double> [[STRIDED_VEC8]], [[STRIDED_VEC16]] ; CHECK-NEXT: [[TMP42:%.*]] = fadd <2 x double> [[STRIDED_VEC9]], [[STRIDED_VEC17]] ; CHECK-NEXT: [[TMP43:%.*]] = fadd <2 x double> [[STRIDED_VEC10]], [[STRIDED_VEC18]] ; CHECK-NEXT: [[TMP44:%.*]] = fadd <2 x double> [[STRIDED_VEC11]], [[STRIDED_VEC19]] ; CHECK-NEXT: [[TMP45:%.*]] = fadd <2 x double> [[STRIDED_VEC12]], [[STRIDED_VEC20]] ; CHECK-NEXT: [[TMP46:%.*]] = fadd <2 x double> [[STRIDED_VEC13]], [[STRIDED_VEC21]] ; CHECK-NEXT: [[TMP47:%.*]] = fadd <2 x double> [[STRIDED_VEC14]], [[STRIDED_VEC22]] ; CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds double, double* [[A:%.*]], i64 [[TMP0]] ; CHECK-NEXT: [[TMP49:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP1]] ; CHECK-NEXT: [[TMP50:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP2]] ; CHECK-NEXT: [[TMP51:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP3]] ; CHECK-NEXT: [[TMP52:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP4]] ; CHECK-NEXT: [[TMP53:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP5]] ; CHECK-NEXT: [[TMP54:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP6]] ; CHECK-NEXT: [[TMP55:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP7]] ; CHECK-NEXT: [[TMP56:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 0 ; CHECK-NEXT: [[TMP57:%.*]] = bitcast double* [[TMP56]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP40]], <2 x double>* [[TMP57]], align 8 ; CHECK-NEXT: [[TMP58:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 2 ; CHECK-NEXT: [[TMP59:%.*]] = bitcast double* [[TMP58]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP41]], <2 x double>* [[TMP59]], align 8 ; CHECK-NEXT: [[TMP60:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 4 ; CHECK-NEXT: [[TMP61:%.*]] = bitcast double* [[TMP60]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP42]], <2 x double>* [[TMP61]], align 8 ; CHECK-NEXT: [[TMP62:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 6 ; CHECK-NEXT: [[TMP63:%.*]] = bitcast double* [[TMP62]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP43]], <2 x double>* [[TMP63]], align 8 ; CHECK-NEXT: [[TMP64:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 8 ; CHECK-NEXT: [[TMP65:%.*]] = bitcast double* [[TMP64]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP44]], <2 x double>* [[TMP65]], align 8 ; CHECK-NEXT: [[TMP66:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 10 ; CHECK-NEXT: [[TMP67:%.*]] = bitcast double* [[TMP66]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP45]], <2 x double>* [[TMP67]], align 8 ; CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 12 ; CHECK-NEXT: [[TMP69:%.*]] = bitcast double* [[TMP68]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP46]], <2 x double>* [[TMP69]], align 8 ; CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 14 ; CHECK-NEXT: [[TMP71:%.*]] = bitcast double* [[TMP70]] to <2 x double>* ; CHECK-NEXT: store <2 x double> [[TMP47]], <2 x double>* [[TMP71]], align 8 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP72:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1600 ; CHECK-NEXT: br i1 [[TMP72]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1600, 1600 ; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1600, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret void ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: [[TMP73:%.*]] = shl nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[ODD_IDX:%.*]] = add nsw i64 [[TMP73]], 1 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP73]] ; CHECK-NEXT: [[ARRAYIDX_ODD:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[ODD_IDX]] ; CHECK-NEXT: [[TMP74:%.*]] = load double, double* [[ARRAYIDX]], align 8 ; CHECK-NEXT: [[TMP75:%.*]] = load double, double* [[ARRAYIDX_ODD]], align 8 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP74]], [[TMP75]] ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[INDVARS_IV]] ; CHECK-NEXT: store double [[ADD]], double* [[ARRAYIDX2]], align 8 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 1600 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]] ; entry: br label %for.body for.cond.cleanup: ; preds = %for.body ret void for.body: ; preds = %for.body, %entry %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] %0 = shl nsw i64 %indvars.iv, 1 %odd.idx = add nsw i64 %0, 1 %arrayidx = getelementptr inbounds double, double* %b, i64 %0 %arrayidx.odd = getelementptr inbounds double, double* %b, i64 %odd.idx %1 = load double, double* %arrayidx, align 8 %2 = load double, double* %arrayidx.odd, align 8 %add = fadd double %1, %2 %arrayidx2 = getelementptr inbounds double, double* %a, i64 %indvars.iv store double %add, double* %arrayidx2, align 8 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 %exitcond = icmp eq i64 %indvars.iv.next, 1600 br i1 %exitcond, label %for.cond.cleanup, label %for.body } attributes #0 = { nounwind "target-cpu"="pwr8" }