1634 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --filter-out-after "^scalar.ph:"2; RUN: opt -mtriple=aarch64-none-linux-gnu -S -passes=loop-vectorize,instcombine -force-vector-width=4 -force-vector-interleave=1 -enable-interleaved-mem-accesses=true -mattr=+sve -scalable-vectorization=on -runtime-memory-check-threshold=24 < %s | FileCheck %s3 4target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"5 6; Check vectorization on an interleaved load group of factor 2 and an interleaved7; store group of factor 2.8 9; int AB[1024];10; int CD[1024];11; void test_array_load2_store2(int C, int D) {12; for (int i = 0; i < 1024; i+=2) {13; int A = AB[i];14; int B = AB[i+1];15; CD[i] = A + C;16; CD[i+1] = B * D;17; }18; }19 20 21@AB = common global [1024 x i32] zeroinitializer, align 422@CD = common global [1024 x i32] zeroinitializer, align 423 24define void @test_array_load2_store2(i32 %C, i32 %D) #1 {25; CHECK-LABEL: @test_array_load2_store2(26; CHECK-NEXT: entry:27; CHECK-NEXT: br label [[VECTOR_PH:%.*]]28; CHECK: vector.ph:29; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()30; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 231; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[C:%.*]], i64 032; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer33; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[D:%.*]], i64 034; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer35; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]36; CHECK: vector.body:37; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]38; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 139; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr @AB, i64 [[OFFSET_IDX]]40; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP2]], align 441; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])42; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 043; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 144; CHECK-NEXT: [[TMP6:%.*]] = add nsw <vscale x 4 x i32> [[TMP3]], [[BROADCAST_SPLAT]]45; CHECK-NEXT: [[TMP7:%.*]] = mul nsw <vscale x 4 x i32> [[TMP4]], [[BROADCAST_SPLAT2]]46; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr @CD, i64 [[OFFSET_IDX]]47; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[TMP6]], <vscale x 4 x i32> [[TMP7]])48; CHECK-NEXT: store <vscale x 8 x i32> [[INTERLEAVED_VEC]], ptr [[TMP8]], align 449; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]50; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 51251; CHECK-NEXT: br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]52; CHECK: middle.block:53; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH:%.*]]54; CHECK: scalar.ph:55;56entry:57 br label %for.body58 59for.body: ; preds = %for.body, %entry60 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]61 %arrayidx0 = getelementptr inbounds [1024 x i32], ptr @AB, i64 0, i64 %indvars.iv62 %load1 = load i32, ptr %arrayidx0, align 463 %or = or disjoint i64 %indvars.iv, 164 %arrayidx1 = getelementptr inbounds [1024 x i32], ptr @AB, i64 0, i64 %or65 %load2 = load i32, ptr %arrayidx1, align 466 %add = add nsw i32 %load1, %C67 %mul = mul nsw i32 %load2, %D68 %arrayidx2 = getelementptr inbounds [1024 x i32], ptr @CD, i64 0, i64 %indvars.iv69 store i32 %add, ptr %arrayidx2, align 470 %arrayidx3 = getelementptr inbounds [1024 x i32], ptr @CD, i64 0, i64 %or71 store i32 %mul, ptr %arrayidx3, align 472 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 273 %cmp = icmp slt i64 %indvars.iv.next, 102474 br i1 %cmp, label %for.body, label %for.end75 76for.end: ; preds = %for.body77 ret void78}79 80; Check vectorization on an interleaved load group of factor 2 with narrower types and an interleaved81; store group of factor 2.82 83; short AB[1024];84; int CD[1024];85; void test_array_load2_store2(int C, int D) {86; for (int i = 0; i < 1024; i+=2) {87; short A = AB[i];88; short B = AB[i+1];89; CD[i] = A + C;90; CD[i+1] = B * D;91; }92; }93 94 95@AB_i16 = common global [1024 x i16] zeroinitializer, align 496 97define void @test_array_load2_i16_store2(i32 %C, i32 %D) #1 {98; CHECK-LABEL: @test_array_load2_i16_store2(99; CHECK-NEXT: entry:100; CHECK-NEXT: br label [[VECTOR_PH:%.*]]101; CHECK: vector.ph:102; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()103; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2104; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[C:%.*]], i64 0105; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer106; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[D:%.*]], i64 0107; CHECK-NEXT: [[BROADCAST_SPLAT3:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer108; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()109; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw <vscale x 4 x i64> [[TMP2]], splat (i64 1)110; CHECK-NEXT: [[TMP5:%.*]] = shl nuw nsw i64 [[TMP0]], 3111; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP5]], i64 0112; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer113; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]114; CHECK: vector.body:115; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]116; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP3]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]117; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr @AB_i16, <vscale x 4 x i64> [[VEC_IND]]118; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i16> @llvm.masked.gather.nxv4i16.nxv4p0(<vscale x 4 x ptr> align 2 [[TMP6]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i16> poison)119; CHECK-NEXT: [[TMP7:%.*]] = or disjoint <vscale x 4 x i64> [[VEC_IND]], splat (i64 1)120; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i16, ptr @AB_i16, <vscale x 4 x i64> [[TMP7]]121; CHECK-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call <vscale x 4 x i16> @llvm.masked.gather.nxv4i16.nxv4p0(<vscale x 4 x ptr> align 2 [[TMP8]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i16> poison)122; CHECK-NEXT: [[TMP9:%.*]] = sext <vscale x 4 x i16> [[WIDE_MASKED_GATHER]] to <vscale x 4 x i32>123; CHECK-NEXT: [[TMP10:%.*]] = add nsw <vscale x 4 x i32> [[BROADCAST_SPLAT]], [[TMP9]]124; CHECK-NEXT: [[DOTIDX:%.*]] = shl i64 [[INDEX]], 3125; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i8, ptr @CD, i64 [[DOTIDX]]126; CHECK-NEXT: [[TMP11:%.*]] = sext <vscale x 4 x i16> [[WIDE_MASKED_GATHER1]] to <vscale x 4 x i32>127; CHECK-NEXT: [[TMP12:%.*]] = mul nsw <vscale x 4 x i32> [[BROADCAST_SPLAT3]], [[TMP11]]128; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[TMP10]], <vscale x 4 x i32> [[TMP12]])129; CHECK-NEXT: store <vscale x 8 x i32> [[INTERLEAVED_VEC]], ptr [[TMP14]], align 4130; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]131; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]132; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 512133; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]134; CHECK: middle.block:135; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH:%.*]]136; CHECK: scalar.ph:137;138entry:139 br label %for.body140 141for.body: ; preds = %entry, %for.body142 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]143 %arrayidx = getelementptr inbounds [1024 x i16], ptr @AB_i16, i64 0, i64 %indvars.iv144 %0 = load i16, ptr %arrayidx, align 2145 %1 = or disjoint i64 %indvars.iv, 1146 %arrayidx2 = getelementptr inbounds [1024 x i16], ptr @AB_i16, i64 0, i64 %1147 %2 = load i16, ptr %arrayidx2, align 2148 %conv = sext i16 %0 to i32149 %add3 = add nsw i32 %conv, %C150 %arrayidx5 = getelementptr inbounds [1024 x i32], ptr @CD, i64 0, i64 %indvars.iv151 store i32 %add3, ptr %arrayidx5, align 4152 %conv6 = sext i16 %2 to i32153 %mul = mul nsw i32 %conv6, %D154 %arrayidx9 = getelementptr inbounds [1024 x i32], ptr @CD, i64 0, i64 %1155 store i32 %mul, ptr %arrayidx9, align 4156 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2157 %cmp = icmp ult i64 %indvars.iv, 1022158 br i1 %cmp, label %for.body, label %for.end159 160for.end: ; preds = %for.body161 ret void162}163 164; Check vectorization on an interleaved load group of factor 2 and an interleaved165; store group of factor 2 with narrower types.166 167; int AB[1024];168; short CD[1024];169; void test_array_load2_store2(int C, int D) {170; for (int i = 0; i < 1024; i+=2) {171; short A = AB[i];172; short B = AB[i+1];173; CD[i] = A + C;174; CD[i+1] = B * D;175; }176; }177 178 179@CD_i16 = dso_local local_unnamed_addr global [1024 x i16] zeroinitializer, align 2180 181define void @test_array_load2_store2_i16(i32 noundef %C, i32 noundef %D) #1 {182; CHECK-LABEL: @test_array_load2_store2_i16(183; CHECK-NEXT: entry:184; CHECK-NEXT: br label [[VECTOR_PH:%.*]]185; CHECK: vector.ph:186; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()187; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2188; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[C:%.*]], i64 0189; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer190; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[D:%.*]], i64 0191; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer192; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()193; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw <vscale x 4 x i64> [[TMP2]], splat (i64 1)194; CHECK-NEXT: [[TMP5:%.*]] = shl nuw nsw i64 [[TMP0]], 3195; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP5]], i64 0196; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer197; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]198; CHECK: vector.body:199; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]200; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP3]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]201; CHECK-NEXT: [[DOTIDX:%.*]] = shl i64 [[INDEX]], 3202; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr @AB, i64 [[DOTIDX]]203; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP6]], align 4204; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])205; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0206; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 1207; CHECK-NEXT: [[TMP9:%.*]] = or disjoint <vscale x 4 x i64> [[VEC_IND]], splat (i64 1)208; CHECK-NEXT: [[TMP10:%.*]] = add nsw <vscale x 4 x i32> [[TMP7]], [[BROADCAST_SPLAT]]209; CHECK-NEXT: [[TMP11:%.*]] = trunc <vscale x 4 x i32> [[TMP10]] to <vscale x 4 x i16>210; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i16, ptr @CD_i16, <vscale x 4 x i64> [[VEC_IND]]211; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i16.nxv4p0(<vscale x 4 x i16> [[TMP11]], <vscale x 4 x ptr> align 2 [[TMP12]], <vscale x 4 x i1> splat (i1 true))212; CHECK-NEXT: [[TMP13:%.*]] = mul nsw <vscale x 4 x i32> [[TMP8]], [[BROADCAST_SPLAT2]]213; CHECK-NEXT: [[TMP14:%.*]] = trunc <vscale x 4 x i32> [[TMP13]] to <vscale x 4 x i16>214; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i16, ptr @CD_i16, <vscale x 4 x i64> [[TMP9]]215; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i16.nxv4p0(<vscale x 4 x i16> [[TMP14]], <vscale x 4 x ptr> align 2 [[TMP15]], <vscale x 4 x i1> splat (i1 true))216; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]217; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]218; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 512219; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]220; CHECK: middle.block:221; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH:%.*]]222; CHECK: scalar.ph:223;224entry:225 br label %for.body226 227for.body: ; preds = %entry, %for.body228 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]229 %arrayidx = getelementptr inbounds [1024 x i32], ptr @AB, i64 0, i64 %indvars.iv230 %0 = load i32, ptr %arrayidx, align 4231 %1 = or disjoint i64 %indvars.iv, 1232 %arrayidx2 = getelementptr inbounds [1024 x i32], ptr @AB, i64 0, i64 %1233 %2 = load i32, ptr %arrayidx2, align 4234 %add3 = add nsw i32 %0, %C235 %conv = trunc i32 %add3 to i16236 %arrayidx5 = getelementptr inbounds [1024 x i16], ptr @CD_i16, i64 0, i64 %indvars.iv237 store i16 %conv, ptr %arrayidx5, align 2238 %mul = mul nsw i32 %2, %D239 %conv6 = trunc i32 %mul to i16240 %arrayidx9 = getelementptr inbounds [1024 x i16], ptr @CD_i16, i64 0, i64 %1241 store i16 %conv6, ptr %arrayidx9, align 2242 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2243 %cmp = icmp ult i64 %indvars.iv, 1022244 br i1 %cmp, label %for.body, label %for.end245 246for.end: ; preds = %for.body247 ret void248}249 250; Check vectorization on an interleaved load group of factor 6.251; There is no dedicated ldN/stN so use gather instead252 253%struct.ST6 = type { i32, i32, i32, i32, i32, i32 }254 255define i32 @test_struct_load6(ptr %S) #1 {256; CHECK-LABEL: @test_struct_load6(257; CHECK-NEXT: entry:258; CHECK-NEXT: br label [[VECTOR_PH:%.*]]259; CHECK: vector.ph:260; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()261; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2262; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()263; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP1]], i64 0264; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer265; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]266; CHECK: vector.body:267; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]268; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP2]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]269; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <vscale x 4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP16:%.*]], [[VECTOR_BODY]] ]270; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[S:%.*]], <vscale x 4 x i64> [[VEC_IND]]271; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP5]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)272; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[S]], <vscale x 4 x i64> [[VEC_IND]]273; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT]], i64 4274; CHECK-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP6]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)275; CHECK-NEXT: [[DOTSPLIT6:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[S]], <vscale x 4 x i64> [[VEC_IND]]276; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT6]], i64 8277; CHECK-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP7]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)278; CHECK-NEXT: [[DOTSPLIT7:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[S]], <vscale x 4 x i64> [[VEC_IND]]279; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT7]], i64 12280; CHECK-NEXT: [[WIDE_MASKED_GATHER3:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP8]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)281; CHECK-NEXT: [[DOTSPLIT8:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[S]], <vscale x 4 x i64> [[VEC_IND]]282; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT8]], i64 16283; CHECK-NEXT: [[WIDE_MASKED_GATHER4:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP9]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)284; CHECK-NEXT: [[DOTSPLIT9:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[S]], <vscale x 4 x i64> [[VEC_IND]]285; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT9]], i64 20286; CHECK-NEXT: [[WIDE_MASKED_GATHER5:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP10]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)287; CHECK-NEXT: [[TMP11:%.*]] = add <vscale x 4 x i32> [[WIDE_MASKED_GATHER]], [[VEC_PHI]]288; CHECK-NEXT: [[TMP12:%.*]] = add <vscale x 4 x i32> [[TMP11]], [[WIDE_MASKED_GATHER2]]289; CHECK-NEXT: [[TMP13:%.*]] = add <vscale x 4 x i32> [[WIDE_MASKED_GATHER1]], [[WIDE_MASKED_GATHER3]]290; CHECK-NEXT: [[TMP14:%.*]] = add <vscale x 4 x i32> [[TMP13]], [[WIDE_MASKED_GATHER4]]291; CHECK-NEXT: [[TMP15:%.*]] = add <vscale x 4 x i32> [[TMP14]], [[WIDE_MASKED_GATHER5]]292; CHECK-NEXT: [[TMP16]] = sub <vscale x 4 x i32> [[TMP12]], [[TMP15]]293; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]294; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]295; CHECK-NEXT: [[TMP17:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024296; CHECK-NEXT: br i1 [[TMP17]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]297; CHECK: middle.block:298; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH:%.*]]299; CHECK: scalar.ph:300;301entry:302 br label %for.body303 304for.body: ; preds = %entry, %for.body305 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]306 %r.041 = phi i32 [ 0, %entry ], [ %sub14, %for.body ]307 %x = getelementptr inbounds %struct.ST6, ptr %S, i64 %indvars.iv, i32 0308 %0 = load i32, ptr %x, align 4309 %y = getelementptr inbounds %struct.ST6, ptr %S, i64 %indvars.iv, i32 1310 %1 = load i32, ptr %y, align 4311 %z = getelementptr inbounds %struct.ST6, ptr %S, i64 %indvars.iv, i32 2312 %2 = load i32, ptr %z, align 4313 %w = getelementptr inbounds %struct.ST6, ptr %S, i64 %indvars.iv, i32 3314 %3 = load i32, ptr %w, align 4315 %a = getelementptr inbounds %struct.ST6, ptr %S, i64 %indvars.iv, i32 4316 %4 = load i32, ptr %a, align 4317 %b = getelementptr inbounds %struct.ST6, ptr %S, i64 %indvars.iv, i32 5318 %5 = load i32, ptr %b, align 4319 %.neg36 = add i32 %0, %r.041320 %6 = add i32 %.neg36, %2321 %7 = add i32 %1, %3322 %8 = add i32 %7, %4323 %9 = add i32 %8, %5324 %sub14 = sub i32 %6, %9325 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1326 %exitcond.not = icmp eq i64 %indvars.iv.next, 1024327 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body328 329for.cond.cleanup: ; preds = %for.body330 %sub14.lcssa = phi i32 [ %sub14, %for.body ]331 ret i32 %sub14.lcssa332}333 334 335; Check vectorization on a reverse interleaved load group of factor 2 and336; a reverse interleaved store group of factor 2.337 338; struct ST2 {339; int x;340; int y;341; };342;343; void test_reversed_load2_store2(struct ST2 *A, struct ST2 *B) {344; for (int i = 1023; i >= 0; i--) {345; int a = A[i].x + i; // interleaved load of index 0346; int b = A[i].y - i; // interleaved load of index 1347; B[i].x = a; // interleaved store of index 0348; B[i].y = b; // interleaved store of index 1349; }350; }351 352 353%struct.ST2 = type { i32, i32 }354 355define void @test_reversed_load2_store2(ptr noalias nocapture readonly %A, ptr noalias nocapture %B) #1 {356; CHECK-LABEL: @test_reversed_load2_store2(357; CHECK-NEXT: entry:358; CHECK-NEXT: br label [[VECTOR_PH:%.*]]359; CHECK: vector.ph:360; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()361; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2362; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i32> @llvm.stepvector.nxv4i32()363; CHECK-NEXT: [[INDUCTION:%.*]] = sub <vscale x 4 x i32> splat (i32 1023), [[TMP2]]364; CHECK-NEXT: [[TMP3:%.*]] = trunc nuw nsw i64 [[TMP1]] to i32365; CHECK-NEXT: [[DOTNEG:%.*]] = sub nsw i32 0, [[TMP3]]366; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[DOTNEG]], i64 0367; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[DOTSPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer368; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]369; CHECK: vector.body:370; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]371; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i32> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]372; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i64 1023, [[INDEX]]373; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[A:%.*]], i64 [[OFFSET_IDX]]374; CHECK-NEXT: [[TMP6:%.*]] = shl nuw nsw i64 [[TMP0]], 3375; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i64 2, [[TMP6]]376; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 [[TMP8]]377; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP9]], align 4378; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])379; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0380; CHECK-NEXT: [[REVERSE:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP10]])381; CHECK-NEXT: [[TMP11:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 1382; CHECK-NEXT: [[REVERSE1:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP11]])383; CHECK-NEXT: [[TMP12:%.*]] = add nsw <vscale x 4 x i32> [[REVERSE]], [[VEC_IND]]384; CHECK-NEXT: [[TMP13:%.*]] = sub nsw <vscale x 4 x i32> [[REVERSE1]], [[VEC_IND]]385; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_ST2]], ptr [[B:%.*]], i64 [[OFFSET_IDX]]386; CHECK-NEXT: [[TMP15:%.*]] = shl nuw nsw i64 [[TMP0]], 3387; CHECK-NEXT: [[TMP18:%.*]] = sub nsw i64 2, [[TMP15]]388; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 [[TMP18]]389; CHECK-NEXT: [[REVERSE2:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP12]])390; CHECK-NEXT: [[REVERSE3:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP13]])391; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[REVERSE2]], <vscale x 4 x i32> [[REVERSE3]])392; CHECK-NEXT: store <vscale x 8 x i32> [[INTERLEAVED_VEC]], ptr [[TMP19]], align 4393; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]394; CHECK-NEXT: [[VEC_IND_NEXT]] = add <vscale x 4 x i32> [[VEC_IND]], [[DOTSPLAT]]395; CHECK-NEXT: [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024396; CHECK-NEXT: br i1 [[TMP20]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]]397; CHECK: middle.block:398; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH:%.*]]399; CHECK: scalar.ph:400;401entry:402 br label %for.body403 404for.cond.cleanup: ; preds = %for.body405 ret void406 407for.body: ; preds = %for.body, %entry408 %indvars.iv = phi i64 [ 1023, %entry ], [ %indvars.iv.next, %for.body ]409 %x = getelementptr inbounds %struct.ST2, ptr %A, i64 %indvars.iv, i32 0410 %load1 = load i32, ptr %x, align 4411 %trunc = trunc i64 %indvars.iv to i32412 %add = add nsw i32 %load1, %trunc413 %y = getelementptr inbounds %struct.ST2, ptr %A, i64 %indvars.iv, i32 1414 %load2 = load i32, ptr %y, align 4415 %sub = sub nsw i32 %load2, %trunc416 %x5 = getelementptr inbounds %struct.ST2, ptr %B, i64 %indvars.iv, i32 0417 store i32 %add, ptr %x5, align 4418 %y8 = getelementptr inbounds %struct.ST2, ptr %B, i64 %indvars.iv, i32 1419 store i32 %sub, ptr %y8, align 4420 %indvars.iv.next = add nsw i64 %indvars.iv, -1421 %cmp = icmp sgt i64 %indvars.iv, 0422 br i1 %cmp, label %for.body, label %for.cond.cleanup423}424 425; Check vectorization on an interleaved load group of factor 2 with 1 gap426; (missing the load of odd elements). Because the vectorized loop would427; speculatively access memory out-of-bounds, we must execute at least one428; iteration of the scalar loop.429 430; void even_load_static_tc(int *A, int *B) {431; for (unsigned i = 0; i < 1024; i+=2)432; B[i/2] = A[i] * 2;433; }434 435 436define void @even_load_static_tc(ptr noalias nocapture readonly %A, ptr noalias nocapture %B) #1 {437; CHECK-LABEL: @even_load_static_tc(438; CHECK-NEXT: entry:439; CHECK-NEXT: br label [[VECTOR_PH:%.*]]440; CHECK: vector.ph:441; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()442; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2443; CHECK-NEXT: [[N_VEC:%.*]] = sub nuw nsw i64 512, [[TMP1]]444; CHECK-NEXT: [[IND_END:%.*]] = shl nuw nsw i64 [[N_VEC]], 1445; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]446; CHECK: vector.body:447; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]448; CHECK-NEXT: [[DOTIDX:%.*]] = shl i64 [[INDEX]], 3449; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[DOTIDX]]450; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP4]], align 4451; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])452; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0453; CHECK-NEXT: [[TMP6:%.*]] = shl nsw <vscale x 4 x i32> [[TMP5]], splat (i32 1)454; CHECK-NEXT: [[TMP7:%.*]] = and i64 [[INDEX]], 9223372036854775804455; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw i32, ptr [[B:%.*]], i64 [[TMP7]]456; CHECK-NEXT: store <vscale x 4 x i32> [[TMP6]], ptr [[TMP8]], align 4457; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]458; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]459; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]]460; CHECK: middle.block:461; CHECK-NEXT: br label [[SCALAR_PH:%.*]]462; CHECK: scalar.ph:463;464entry:465 br label %for.body466 467for.cond.cleanup: ; preds = %for.body468 ret void469 470for.body: ; preds = %for.body, %entry471 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]472 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv473 %load = load i32, ptr %arrayidx, align 4474 %mul = shl nsw i32 %load, 1475 %lshr = lshr exact i64 %indvars.iv, 1476 %arrayidx2 = getelementptr inbounds i32, ptr %B, i64 %lshr477 store i32 %mul, ptr %arrayidx2, align 4478 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2479 %cmp = icmp ult i64 %indvars.iv.next, 1024480 br i1 %cmp, label %for.body, label %for.cond.cleanup481}482 483; Check vectorization on an interleaved load group of factor 2 with 1 gap484; (missing the load of odd elements). Because the vectorized loop would485; speculatively access memory out-of-bounds, we must execute at least one486; iteration of the scalar loop.487 488; void even_load_dynamic_tc(int *A, int *B, unsigned N) {489; for (unsigned i = 0; i < N; i+=2)490; B[i/2] = A[i] * 2;491; }492 493 494define void @even_load_dynamic_tc(ptr noalias nocapture readonly %A, ptr noalias nocapture %B, i64 %N) #1 {495; CHECK-LABEL: @even_load_dynamic_tc(496; CHECK-NEXT: entry:497; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 2)498; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[UMAX]], -1499; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 1500; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()501; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP2]], 2502; CHECK-NEXT: [[MIN_ITERS_CHECK_NOT_NOT:%.*]] = icmp samesign ult i64 [[TMP1]], [[TMP3]]503; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK_NOT_NOT]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]504; CHECK: vector.ph:505; CHECK-NEXT: [[TMP4:%.*]] = add nuw i64 [[TMP1]], 1506; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()507; CHECK-NEXT: [[TMP6:%.*]] = shl nuw nsw i64 [[TMP5]], 2508; CHECK-NEXT: [[TMP7:%.*]] = add nsw i64 [[TMP6]], -1509; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP4]], [[TMP7]]510; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[N_MOD_VF]], 0511; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 [[TMP6]], i64 [[N_MOD_VF]]512; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP4]], [[TMP9]]513; CHECK-NEXT: [[IND_END:%.*]] = shl i64 [[N_VEC]], 1514; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]515; CHECK: vector.body:516; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]517; CHECK-NEXT: [[DOTIDX:%.*]] = shl i64 [[INDEX]], 3518; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[DOTIDX]]519; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP12]], align 4520; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])521; CHECK-NEXT: [[TMP13:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0522; CHECK-NEXT: [[TMP14:%.*]] = shl nsw <vscale x 4 x i32> [[TMP13]], splat (i32 1)523; CHECK-NEXT: [[TMP15:%.*]] = and i64 [[INDEX]], 9223372036854775804524; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw i32, ptr [[B:%.*]], i64 [[TMP15]]525; CHECK-NEXT: store <vscale x 4 x i32> [[TMP14]], ptr [[TMP16]], align 4526; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]]527; CHECK-NEXT: [[TMP17:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]528; CHECK-NEXT: br i1 [[TMP17]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]]529; CHECK: middle.block:530; CHECK-NEXT: br label [[SCALAR_PH]]531; CHECK: scalar.ph:532;533entry:534 br label %for.body535 536for.cond.cleanup: ; preds = %for.body537 ret void538 539for.body: ; preds = %for.body, %entry540 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]541 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv542 %load = load i32, ptr %arrayidx, align 4543 %mul = shl nsw i32 %load, 1544 %lshr = lshr exact i64 %indvars.iv, 1545 %arrayidx2 = getelementptr inbounds i32, ptr %B, i64 %lshr546 store i32 %mul, ptr %arrayidx2, align 4547 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2548 %cmp = icmp ult i64 %indvars.iv.next, %N549 br i1 %cmp, label %for.body, label %for.cond.cleanup550}551 552; Check vectorization on a reverse interleaved load group of factor 2 with 1553; gap and a reverse interleaved store group of factor 2. The interleaved load554; group should be removed since it has a gap and is reverse.555 556; struct pair {557; int x;558; int y;559; };560;561; void load_gap_reverse(struct pair *P1, struct pair *P2, int X) {562; for (int i = 1023; i >= 0; i--) {563; int a = X + i;564; int b = A[i].y - i;565; B[i].x = a;566; B[i].y = b;567; }568; }569 570%pair = type { i64, i64 }571define void @load_gap_reverse(ptr noalias nocapture readonly %P1, ptr noalias nocapture readonly %P2, i64 %X) #1 {572; CHECK-LABEL: @load_gap_reverse(573; CHECK-NEXT: entry:574; CHECK-NEXT: br label [[VECTOR_PH:%.*]]575; CHECK: vector.ph:576; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()577; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2578; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[X:%.*]], i64 0579; CHECK-NEXT: [[BROADCAST_SPLAT1:%.*]] = shufflevector <vscale x 4 x i64> [[BROADCAST_SPLATINSERT1]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer580; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()581; CHECK-NEXT: [[INDUCTION:%.*]] = sub <vscale x 4 x i64> splat (i64 1023), [[TMP2]]582; CHECK-NEXT: [[DOTNEG:%.*]] = sub nsw i64 0, [[TMP1]]583; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[DOTNEG]], i64 0584; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer585; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]586; CHECK: vector.body:587; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]588; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]589; CHECK-NEXT: [[TMP4:%.*]] = add nsw <vscale x 4 x i64> [[BROADCAST_SPLAT1]], [[VEC_IND]]590; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[PAIR:%.*]], ptr [[P1:%.*]], <vscale x 4 x i64> [[VEC_IND]]591; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[PAIR]], ptr [[P2:%.*]], <vscale x 4 x i64> [[VEC_IND]]592; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT]], i64 8593; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i64> @llvm.masked.gather.nxv4i64.nxv4p0(<vscale x 4 x ptr> align 8 [[TMP6]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i64> poison)594; CHECK-NEXT: [[TMP7:%.*]] = sub nsw <vscale x 4 x i64> [[WIDE_MASKED_GATHER]], [[VEC_IND]]595; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i64.nxv4p0(<vscale x 4 x i64> [[TMP4]], <vscale x 4 x ptr> align 8 [[TMP5]], <vscale x 4 x i1> splat (i1 true))596; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i64.nxv4p0(<vscale x 4 x i64> [[TMP7]], <vscale x 4 x ptr> align 8 [[TMP6]], <vscale x 4 x i1> splat (i1 true))597; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]598; CHECK-NEXT: [[VEC_IND_NEXT]] = add nsw <vscale x 4 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]599; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024600; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]]601; CHECK: middle.block:602; CHECK-NEXT: br i1 true, label [[FOR_EXIT:%.*]], label [[SCALAR_PH:%.*]]603; CHECK: scalar.ph:604;605entry:606 br label %for.body607 608for.body:609 %i = phi i64 [ 1023, %entry ], [ %i.next, %for.body ]610 %0 = add nsw i64 %X, %i611 %1 = getelementptr inbounds %pair, ptr %P1, i64 %i, i32 0612 %2 = getelementptr inbounds %pair, ptr %P2, i64 %i, i32 1613 %3 = load i64, ptr %2, align 8614 %4 = sub nsw i64 %3, %i615 store i64 %0, ptr %1, align 8616 store i64 %4, ptr %2, align 8617 %i.next = add nsw i64 %i, -1618 %cond = icmp sgt i64 %i, 0619 br i1 %cond, label %for.body, label %for.exit620 621for.exit:622 ret void623}624 625; Check vectorization on interleaved access groups identified from mixed626; loads/stores.627; void mixed_load2_store2(int *A, int *B) {628; for (unsigned i = 0; i < 1024; i+=2) {629; B[i] = A[i] * A[i+1];630; B[i+1] = A[i] + A[i+1];631; }632; }633 634 635define void @mixed_load2_store2(ptr noalias nocapture readonly %A, ptr noalias nocapture %B) #1 {636; CHECK-LABEL: @mixed_load2_store2(637; CHECK-NEXT: entry:638; CHECK-NEXT: br label [[VECTOR_PH:%.*]]639; CHECK: vector.ph:640; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()641; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2642; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]643; CHECK: vector.body:644; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]645; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1646; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[OFFSET_IDX]]647; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP2]], align 4648; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])649; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0650; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 1651; CHECK-NEXT: [[TMP6:%.*]] = mul nsw <vscale x 4 x i32> [[TMP4]], [[TMP3]]652; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[OFFSET_IDX]]653; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])654; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 0655; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 1656; CHECK-NEXT: [[TMP9:%.*]] = add nsw <vscale x 4 x i32> [[TMP8]], [[TMP7]]657; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[TMP6]], <vscale x 4 x i32> [[TMP9]])658; CHECK-NEXT: store <vscale x 8 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4659; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]660; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 512661; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]]662; CHECK: middle.block:663; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH:%.*]]664; CHECK: scalar.ph:665;666entry:667 br label %for.body668 669for.cond.cleanup: ; preds = %for.body670 ret void671 672for.body: ; preds = %for.body, %entry673 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]674 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv675 %load1 = load i32, ptr %arrayidx, align 4676 %or = or disjoint i64 %indvars.iv, 1677 %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %or678 %load2 = load i32, ptr %arrayidx2, align 4679 %mul = mul nsw i32 %load2, %load1680 %arrayidx4 = getelementptr inbounds i32, ptr %B, i64 %indvars.iv681 store i32 %mul, ptr %arrayidx4, align 4682 %load3 = load i32, ptr %arrayidx, align 4683 %load4 = load i32, ptr %arrayidx2, align 4684 %add10 = add nsw i32 %load4, %load3685 %arrayidx13 = getelementptr inbounds i32, ptr %B, i64 %or686 store i32 %add10, ptr %arrayidx13, align 4687 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2688 %cmp = icmp ult i64 %indvars.iv.next, 1024689 br i1 %cmp, label %for.body, label %for.cond.cleanup690}691 692 693; Check vectorization on interleaved access groups with members having different694; kinds of type.695 696; struct IntFloat {697; int a;698; float b;699; };700;701; int SA;702; float SB;703;704; void int_float_struct(struct IntFloat *A) {705; int SumA;706; float SumB;707; for (unsigned i = 0; i < 1024; i++) {708; SumA += A[i].a;709; SumB += A[i].b;710; }711; SA = SumA;712; SB = SumB;713; }714 715 716%struct.IntFloat = type { i32, float }717 718@SA = common global i32 0, align 4719@SB = common global float 0.000000e+00, align 4720 721define void @int_float_struct(ptr nocapture readonly %p) #0 {722; CHECK-LABEL: @int_float_struct(723; CHECK-NEXT: entry:724; CHECK-NEXT: br label [[VECTOR_PH:%.*]]725; CHECK: vector.ph:726; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()727; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2728; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]729; CHECK: vector.body:730; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]731; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <vscale x 4 x float> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP7:%.*]], [[VECTOR_BODY]] ]732; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <vscale x 4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ]733; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_INTFLOAT:%.*]], ptr [[P:%.*]], i64 [[INDEX]]734; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP2]], align 4735; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])736; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0737; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 1738; CHECK-NEXT: [[TMP5:%.*]] = bitcast <vscale x 4 x i32> [[TMP4]] to <vscale x 4 x float>739; CHECK-NEXT: [[TMP6]] = add <vscale x 4 x i32> [[TMP3]], [[VEC_PHI1]]740; CHECK-NEXT: [[TMP7]] = fadd fast <vscale x 4 x float> [[VEC_PHI]], [[TMP5]]741; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]742; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024743; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]]744; CHECK: middle.block:745; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH:%.*]]746; CHECK: scalar.ph:747;748entry:749 br label %for.body750 751for.cond.cleanup: ; preds = %for.body752 store i32 %add, ptr @SA, align 4753 store float %add3, ptr @SB, align 4754 ret void755 756for.body: ; preds = %for.body, %entry757 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]758 %SumB.014 = phi float [ 0.0e+00, %entry ], [ %add3, %for.body ]759 %SumA.013 = phi i32 [ 0, %entry ], [ %add, %for.body ]760 %a = getelementptr inbounds %struct.IntFloat, ptr %p, i64 %indvars.iv, i32 0761 %load1 = load i32, ptr %a, align 4762 %add = add nsw i32 %load1, %SumA.013763 %b = getelementptr inbounds %struct.IntFloat, ptr %p, i64 %indvars.iv, i32 1764 %load2 = load float, ptr %b, align 4765 %add3 = fadd fast float %SumB.014, %load2766 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1767 %exitcond = icmp eq i64 %indvars.iv.next, 1024768 br i1 %exitcond, label %for.cond.cleanup, label %for.body769}770 771; Check vectorization of interleaved access groups in the presence of772; dependences (PR27626). The following tests check that we don't reorder773; dependent loads and stores when generating code for interleaved access774; groups. Stores should be scalarized because the required code motion would775; break dependences, and the remaining interleaved load groups should have776; gaps.777 778; PR27626_0: Ensure a strided store is not moved after a dependent (zero779; distance) strided load.780 781; void PR27626_0(struct pair *p, int z, int n) {782; for (int i = 0; i < n; i++) {783; p[i].x = z;784; p[i].y = p[i].x;785; }786; }787 788%pair.i32 = type { i32, i32 }789define void @PR27626_0(ptr %p, i32 %z, i64 %n) #1 {790; CHECK-LABEL: @PR27626_0(791; CHECK-NEXT: entry:792; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)793; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()794; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2795; CHECK-NEXT: [[MIN_ITERS_CHECK_NOT:%.*]] = icmp samesign ugt i64 [[SMAX]], [[TMP1]]796; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK_NOT]], label [[VECTOR_PH:%.*]], label [[SCALAR_PH:%.*]]797; CHECK: vector.ph:798; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()799; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP2]], 2800; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP3]], -1801; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[SMAX]], [[TMP4]]802; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 0803; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 [[TMP3]], i64 [[N_MOD_VF]]804; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[SMAX]], [[TMP6]]805; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[Z:%.*]], i64 0806; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer807; CHECK-NEXT: [[TMP9:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()808; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP3]], i64 0809; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer810; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]811; CHECK: vector.body:812; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]813; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP9]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]814; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[PAIR_I32:%.*]], ptr [[P:%.*]], <vscale x 4 x i64> [[VEC_IND]]815; CHECK-NEXT: [[TMP14:%.*]] = extractelement <vscale x 4 x ptr> [[TMP12]], i64 0816; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[PAIR_I32]], ptr [[P]], <vscale x 4 x i64> [[VEC_IND]]817; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT]], i64 4818; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[BROADCAST_SPLAT]], <vscale x 4 x ptr> align 4 [[TMP12]], <vscale x 4 x i1> splat (i1 true))819; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP14]], align 4820; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])821; CHECK-NEXT: [[TMP15:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0822; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP15]], <vscale x 4 x ptr> align 4 [[TMP13]], <vscale x 4 x i1> splat (i1 true))823; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP3]]824; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]825; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]826; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]]827; CHECK: middle.block:828; CHECK-NEXT: br label [[SCALAR_PH]]829; CHECK: scalar.ph:830;831entry:832 br label %for.body833 834for.body:835 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]836 %p_i.x = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 0837 %p_i.y = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 1838 store i32 %z, ptr %p_i.x, align 4839 %0 = load i32, ptr %p_i.x, align 4840 store i32 %0, ptr %p_i.y, align 4841 %i.next = add nuw nsw i64 %i, 1842 %cond = icmp slt i64 %i.next, %n843 br i1 %cond, label %for.body, label %for.end844 845for.end:846 ret void847}848 849; PR27626_1: Ensure a strided load is not moved before a dependent (zero850; distance) strided store.851 852; void PR27626_1(struct pair *p, int n) {853; int s = 0;854; for (int i = 0; i < n; i++) {855; p[i].y = p[i].x;856; s += p[i].y857; }858; }859 860define i32 @PR27626_1(ptr %p, i64 %n) #1 {861; CHECK-LABEL: @PR27626_1(862; CHECK-NEXT: entry:863; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)864; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()865; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2866; CHECK-NEXT: [[MIN_ITERS_CHECK_NOT:%.*]] = icmp samesign ugt i64 [[SMAX]], [[TMP1]]867; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK_NOT]], label [[VECTOR_PH:%.*]], label [[SCALAR_PH:%.*]]868; CHECK: vector.ph:869; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()870; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP2]], 2871; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP3]], -1872; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[SMAX]], [[TMP4]]873; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 0874; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 [[TMP3]], i64 [[N_MOD_VF]]875; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[SMAX]], [[TMP6]]876; CHECK-NEXT: [[TMP9:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()877; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP3]], i64 0878; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer879; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]880; CHECK: vector.body:881; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]882; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP9]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]883; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <vscale x 4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP17:%.*]], [[VECTOR_BODY]] ]884; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[PAIR_I32:%.*]], ptr [[P:%.*]], i64 [[INDEX]]885; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[PAIR_I32]], ptr [[P]], <vscale x 4 x i64> [[VEC_IND]]886; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT]], i64 4887; CHECK-NEXT: [[TMP15:%.*]] = extractelement <vscale x 4 x ptr> [[TMP13]], i64 0888; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP12]], align 4889; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])890; CHECK-NEXT: [[TMP14:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0891; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP14]], <vscale x 4 x ptr> align 4 [[TMP13]], <vscale x 4 x i1> splat (i1 true))892; CHECK-NEXT: [[WIDE_VEC1:%.*]] = load <vscale x 8 x i32>, ptr [[TMP15]], align 4893; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC1]])894; CHECK-NEXT: [[TMP16:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 0895; CHECK-NEXT: [[TMP17]] = add <vscale x 4 x i32> [[TMP16]], [[VEC_PHI]]896; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP3]]897; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]898; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]899; CHECK-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]]900; CHECK: middle.block:901; CHECK-NEXT: [[TMP19:%.*]] = call i32 @llvm.vector.reduce.add.nxv4i32(<vscale x 4 x i32> [[TMP17]])902; CHECK-NEXT: br label [[SCALAR_PH]]903; CHECK: scalar.ph:904;905entry:906 br label %for.body907 908for.body:909 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]910 %s = phi i32 [ %2, %for.body ], [ 0, %entry ]911 %p_i.x = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 0912 %p_i.y = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 1913 %0 = load i32, ptr %p_i.x, align 4914 store i32 %0, ptr %p_i.y, align 4915 %1 = load i32, ptr %p_i.y, align 4916 %2 = add nsw i32 %1, %s917 %i.next = add nuw nsw i64 %i, 1918 %cond = icmp slt i64 %i.next, %n919 br i1 %cond, label %for.body, label %for.end920 921for.end:922 %3 = phi i32 [ %2, %for.body ]923 ret i32 %3924}925 926; PR27626_2: Ensure a strided store is not moved after a dependent (negative927; distance) strided load.928 929; void PR27626_2(struct pair *p, int z, int n) {930; for (int i = 0; i < n; i++) {931; p[i].x = z;932; p[i].y = p[i - 1].x;933; }934; }935 936define void @PR27626_2(ptr %p, i64 %n, i32 %z) #1 {937; CHECK-LABEL: @PR27626_2(938; CHECK-NEXT: entry:939; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)940; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()941; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2942; CHECK-NEXT: [[MIN_ITERS_CHECK_NOT:%.*]] = icmp samesign ugt i64 [[SMAX]], [[TMP1]]943; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK_NOT]], label [[VECTOR_PH:%.*]], label [[SCALAR_PH:%.*]]944; CHECK: vector.ph:945; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()946; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP2]], 2947; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP3]], -1948; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[SMAX]], [[TMP4]]949; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 0950; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 [[TMP3]], i64 [[N_MOD_VF]]951; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[SMAX]], [[TMP6]]952; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[Z:%.*]], i64 0953; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer954; CHECK-NEXT: [[TMP9:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()955; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP3]], i64 0956; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer957; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]958; CHECK: vector.body:959; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]960; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP9]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]961; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[PAIR_I32:%.*]], ptr [[P:%.*]], <vscale x 4 x i64> [[VEC_IND]]962; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 -8963; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[PAIR_I32]], ptr [[P]], <vscale x 4 x i64> [[VEC_IND]]964; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT]], i64 4965; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[BROADCAST_SPLAT]], <vscale x 4 x ptr> align 4 [[TMP12]], <vscale x 4 x i1> splat (i1 true))966; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP13]], align 4967; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])968; CHECK-NEXT: [[TMP15:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0969; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP15]], <vscale x 4 x ptr> align 4 [[TMP14]], <vscale x 4 x i1> splat (i1 true))970; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP3]]971; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]972; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]973; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]]974; CHECK: middle.block:975; CHECK-NEXT: br label [[SCALAR_PH]]976; CHECK: scalar.ph:977;978entry:979 br label %for.body980 981for.body:982 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]983 %i_minus_1 = add nuw nsw i64 %i, -1984 %p_i.x = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 0985 %p_i_minus_1.x = getelementptr inbounds %pair.i32, ptr %p, i64 %i_minus_1, i32 0986 %p_i.y = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 1987 store i32 %z, ptr %p_i.x, align 4988 %0 = load i32, ptr %p_i_minus_1.x, align 4989 store i32 %0, ptr %p_i.y, align 4990 %i.next = add nuw nsw i64 %i, 1991 %cond = icmp slt i64 %i.next, %n992 br i1 %cond, label %for.body, label %for.end993 994for.end:995 ret void996}997 998; PR27626_3: Ensure a strided load is not moved before a dependent (negative999; distance) strided store.1000 1001; void PR27626_3(struct pair *p, int z, int n) {1002; for (int i = 0; i < n; i++) {1003; p[i + 1].y = p[i].x;1004; s += p[i].y;1005; }1006; }1007 1008define i32 @PR27626_3(ptr %p, i64 %n, i32 %z) #1 {1009; CHECK-LABEL: @PR27626_3(1010; CHECK-NEXT: entry:1011; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)1012; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()1013; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 21014; CHECK-NEXT: [[MIN_ITERS_CHECK_NOT:%.*]] = icmp samesign ugt i64 [[SMAX]], [[TMP1]]1015; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK_NOT]], label [[VECTOR_PH:%.*]], label [[SCALAR_PH:%.*]]1016; CHECK: vector.ph:1017; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()1018; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP2]], 21019; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP3]], -11020; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[SMAX]], [[TMP4]]1021; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[N_MOD_VF]], 01022; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 [[TMP3]], i64 [[N_MOD_VF]]1023; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[SMAX]], [[TMP6]]1024; CHECK-NEXT: [[TMP9:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()1025; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP3]], i64 01026; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer1027; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1028; CHECK: vector.body:1029; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1030; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP9]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]1031; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <vscale x 4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP18:%.*]], [[VECTOR_BODY]] ]1032; CHECK-NEXT: [[TMP12:%.*]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], splat (i64 1)1033; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[PAIR_I32:%.*]], ptr [[P:%.*]], i64 [[INDEX]]1034; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[PAIR_I32]], ptr [[P]], i64 [[INDEX]]1035; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 41036; CHECK-NEXT: [[DOTSPLIT3:%.*]] = getelementptr inbounds [[PAIR_I32]], ptr [[P]], <vscale x 4 x i64> [[TMP12]]1037; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i8, <vscale x 4 x ptr> [[DOTSPLIT3]], i64 41038; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP13]], align 41039; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]])1040; CHECK-NEXT: [[TMP16:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 01041; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP16]], <vscale x 4 x ptr> align 4 [[TMP15]], <vscale x 4 x i1> splat (i1 true))1042; CHECK-NEXT: [[WIDE_VEC1:%.*]] = load <vscale x 8 x i32>, ptr [[TMP14]], align 41043; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC1]])1044; CHECK-NEXT: [[TMP17:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 01045; CHECK-NEXT: [[TMP18]] = add <vscale x 4 x i32> [[TMP17]], [[VEC_PHI]]1046; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP3]]1047; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]1048; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]1049; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]]1050; CHECK: middle.block:1051; CHECK-NEXT: [[TMP20:%.*]] = call i32 @llvm.vector.reduce.add.nxv4i32(<vscale x 4 x i32> [[TMP18]])1052; CHECK-NEXT: br label [[SCALAR_PH]]1053; CHECK: scalar.ph:1054;1055entry:1056 br label %for.body1057 1058for.body:1059 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]1060 %s = phi i32 [ %2, %for.body ], [ 0, %entry ]1061 %i_plus_1 = add nuw nsw i64 %i, 11062 %p_i.x = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 01063 %p_i.y = getelementptr inbounds %pair.i32, ptr %p, i64 %i, i32 11064 %p_i_plus_1.y = getelementptr inbounds %pair.i32, ptr %p, i64 %i_plus_1, i32 11065 %0 = load i32, ptr %p_i.x, align 41066 store i32 %0, ptr %p_i_plus_1.y, align 41067 %1 = load i32, ptr %p_i.y, align 41068 %2 = add nsw i32 %1, %s1069 %i.next = add nuw nsw i64 %i, 11070 %cond = icmp slt i64 %i.next, %n1071 br i1 %cond, label %for.body, label %for.end1072 1073for.end:1074 %3 = phi i32 [ %2, %for.body ]1075 ret i32 %31076}1077 1078; PR27626_4: Ensure we form an interleaved group for strided stores in the1079; presence of a write-after-write dependence. We create a group for1080; (2) and (3) while excluding (1).1081 1082; void PR27626_4(int *a, int x, int y, int z, int n) {1083; for (int i = 0; i < n; i += 2) {1084; a[i] = x; // (1)1085; a[i] = y; // (2)1086; a[i + 1] = z; // (3)1087; }1088; }1089 1090define void @PR27626_4(ptr %a, i32 %x, i32 %y, i32 %z, i64 %n) #1 {1091; CHECK-LABEL: @PR27626_4(1092; CHECK-NEXT: entry:1093; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 2)1094; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -11095; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 11096; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 11097; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64()1098; CHECK-NEXT: [[TMP4:%.*]] = shl nuw nsw i64 [[TMP3]], 21099; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp samesign ult i64 [[TMP2]], [[TMP4]]1100; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]1101; CHECK: vector.ph:1102; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64()1103; CHECK-NEXT: [[TMP7:%.*]] = shl nuw nsw i64 [[TMP6]], 21104; CHECK-NEXT: [[DOTNOT:%.*]] = sub nsw i64 0, [[TMP7]]1105; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], [[DOTNOT]]1106; CHECK-NEXT: [[IND_END:%.*]] = shl nuw i64 [[N_VEC]], 11107; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[X:%.*]], i64 01108; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1109; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[Y:%.*]], i64 01110; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1111; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[Z:%.*]], i64 01112; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT3]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1113; CHECK-NEXT: [[TMP10:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()1114; CHECK-NEXT: [[TMP9:%.*]] = shl nuw nsw <vscale x 4 x i64> [[TMP10]], splat (i64 1)1115; CHECK-NEXT: [[TMP11:%.*]] = shl nuw nsw i64 [[TMP6]], 31116; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP11]], i64 01117; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer1118; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1119; CHECK: vector.body:1120; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1121; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP9]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]1122; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], <vscale x 4 x i64> [[VEC_IND]]1123; CHECK-NEXT: [[P:%.*]] = extractelement <vscale x 4 x ptr> [[TMP13]], i64 01124; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[BROADCAST_SPLAT]], <vscale x 4 x ptr> align 4 [[TMP13]], <vscale x 4 x i1> splat (i1 true))1125; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[BROADCAST_SPLAT2]], <vscale x 4 x i32> [[BROADCAST_SPLAT4]])1126; CHECK-NEXT: store <vscale x 8 x i32> [[INTERLEAVED_VEC]], ptr [[P]], align 41127; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP7]]1128; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]1129; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]1130; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP30:![0-9]+]]1131; CHECK: middle.block:1132; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]]1133; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]]1134; CHECK: scalar.ph:1135;1136entry:1137 br label %for.body1138 1139for.body:1140 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]1141 %i_plus_1 = add i64 %i, 11142 %a_i = getelementptr inbounds i32, ptr %a, i64 %i1143 %a_i_plus_1 = getelementptr inbounds i32, ptr %a, i64 %i_plus_11144 store i32 %x, ptr %a_i, align 41145 store i32 %y, ptr %a_i, align 41146 store i32 %z, ptr %a_i_plus_1, align 41147 %i.next = add nuw nsw i64 %i, 21148 %cond = icmp slt i64 %i.next, %n1149 br i1 %cond, label %for.body, label %for.end1150 1151for.end:1152 ret void1153}1154 1155; PR27626_5: Ensure we do not form an interleaved group for strided stores in1156; the presence of a write-after-write dependence.1157 1158; void PR27626_5(int *a, int x, int y, int z, int n) {1159; for (int i = 3; i < n; i += 2) {1160; a[i - 1] = x;1161; a[i - 3] = y;1162; a[i] = z;1163; }1164; }1165 1166define void @PR27626_5(ptr %a, i32 %x, i32 %y, i32 %z, i64 %n) #1 {1167; CHECK-LABEL: @PR27626_5(1168; CHECK-NEXT: entry:1169; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 5)1170; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -41171; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 11172; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 11173; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64()1174; CHECK-NEXT: [[TMP4:%.*]] = shl nuw nsw i64 [[TMP3]], 21175; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp samesign ult i64 [[TMP2]], [[TMP4]]1176; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]1177; CHECK: vector.ph:1178; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.vscale.i64()1179; CHECK-NEXT: [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 21180; CHECK-NEXT: [[DOTNOT:%.*]] = sub nsw i64 0, [[TMP8]]1181; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], [[DOTNOT]]1182; CHECK-NEXT: [[TMP11:%.*]] = shl nuw i64 [[N_VEC]], 11183; CHECK-NEXT: [[IND_END:%.*]] = or disjoint i64 [[TMP11]], 31184; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[X:%.*]], i64 01185; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1186; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[Y:%.*]], i64 01187; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1188; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[Z:%.*]], i64 01189; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT3]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1190; CHECK-NEXT: [[TMP10:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()1191; CHECK-NEXT: [[TMP19:%.*]] = shl nuw nsw <vscale x 4 x i64> [[TMP10]], splat (i64 1)1192; CHECK-NEXT: [[INDUCTION:%.*]] = add nuw nsw <vscale x 4 x i64> [[TMP19]], splat (i64 3)1193; CHECK-NEXT: [[TMP12:%.*]] = shl nuw nsw i64 [[TMP7]], 31194; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP12]], i64 01195; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer1196; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1197; CHECK: vector.body:1198; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1199; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]1200; CHECK-NEXT: [[TMP13:%.*]] = add <vscale x 4 x i64> [[VEC_IND]], splat (i64 -1)1201; CHECK-NEXT: [[TMP14:%.*]] = add <vscale x 4 x i64> [[VEC_IND]], splat (i64 -3)1202; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], <vscale x 4 x i64> [[VEC_IND]]1203; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[A]], <vscale x 4 x i64> [[TMP13]]1204; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[A]], <vscale x 4 x i64> [[TMP14]]1205; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[BROADCAST_SPLAT]], <vscale x 4 x ptr> align 4 [[TMP16]], <vscale x 4 x i1> splat (i1 true))1206; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[BROADCAST_SPLAT2]], <vscale x 4 x ptr> align 4 [[TMP17]], <vscale x 4 x i1> splat (i1 true))1207; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[BROADCAST_SPLAT4]], <vscale x 4 x ptr> align 4 [[TMP15]], <vscale x 4 x i1> splat (i1 true))1208; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP8]]1209; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]1210; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]1211; CHECK-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP32:![0-9]+]]1212; CHECK: middle.block:1213; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]]1214; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]]1215; CHECK: scalar.ph:1216;1217entry:1218 br label %for.body1219 1220for.body:1221 %i = phi i64 [ %i.next, %for.body ], [ 3, %entry ]1222 %i_minus_1 = sub i64 %i, 11223 %i_minus_3 = sub i64 %i_minus_1, 21224 %a_i = getelementptr inbounds i32, ptr %a, i64 %i1225 %a_i_minus_1 = getelementptr inbounds i32, ptr %a, i64 %i_minus_11226 %a_i_minus_3 = getelementptr inbounds i32, ptr %a, i64 %i_minus_31227 store i32 %x, ptr %a_i_minus_1, align 41228 store i32 %y, ptr %a_i_minus_3, align 41229 store i32 %z, ptr %a_i, align 41230 %i.next = add nuw nsw i64 %i, 21231 %cond = icmp slt i64 %i.next, %n1232 br i1 %cond, label %for.body, label %for.end1233 1234for.end:1235 ret void1236}1237 1238; PR34743: Ensure that a cast which needs to sink after a load that belongs to1239; an interleaved group, indeeded gets sunk.1240 1241; void PR34743(short *a, int *b, int n) {1242; for (int i = 0, iv = 0; iv < n; i++, iv += 2) {1243; b[i] = a[iv] * a[iv+1] * a[iv+2];1244; }1245; }1246 1247define void @PR34743(ptr %a, ptr %b, i64 %n) #1 {1248; CHECK-LABEL: @PR34743(1249; CHECK-NEXT: entry:1250; CHECK-NEXT: [[DOTPRE:%.*]] = load i16, ptr [[A:%.*]], align 21251; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[N:%.*]], 11252; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[TMP0]], 11253; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()1254; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP2]], 21255; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], [[TMP3]]1256; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]]1257; CHECK: vector.memcheck:1258; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[N]], 11259; CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], -41260; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[B:%.*]], i64 [[TMP5]]1261; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[TMP6]], i64 41262; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr nuw i8, ptr [[A]], i64 21263; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP5]]1264; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[TMP7]], i64 61265; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[B]], [[SCEVGEP2]]1266; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[SCEVGEP1]], [[SCEVGEP]]1267; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]1268; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]1269; CHECK: vector.ph:1270; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64()1271; CHECK-NEXT: [[TMP10:%.*]] = shl nuw nsw i64 [[TMP9]], 21272; CHECK-NEXT: [[DOTNOT:%.*]] = sub nsw i64 0, [[TMP10]]1273; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP1]], [[DOTNOT]]1274; CHECK-NEXT: [[IND_END:%.*]] = shl i64 [[N_VEC]], 11275; CHECK-NEXT: [[TMP14:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()1276; CHECK-NEXT: [[TMP15:%.*]] = shl nuw nsw <vscale x 4 x i64> [[TMP14]], splat (i64 1)1277; CHECK-NEXT: [[TMP17:%.*]] = shl nuw nsw i64 [[TMP9]], 31278; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP17]], i64 01279; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer1280; CHECK-NEXT: [[TMP33:%.*]] = call i32 @llvm.vscale.i32()1281; CHECK-NEXT: [[TMP16:%.*]] = shl nuw nsw i32 [[TMP33]], 21282; CHECK-NEXT: [[TMP34:%.*]] = add nsw i32 [[TMP16]], -11283; CHECK-NEXT: [[VECTOR_RECUR_INIT:%.*]] = insertelement <vscale x 4 x i16> poison, i16 [[DOTPRE]], i32 [[TMP34]]1284; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1285; CHECK: vector.body:1286; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1287; CHECK-NEXT: [[VECTOR_RECUR:%.*]] = phi <vscale x 4 x i16> [ [[VECTOR_RECUR_INIT]], [[VECTOR_PH]] ], [ [[WIDE_MASKED_GATHER4:%.*]], [[VECTOR_BODY]] ]1288; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP15]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]1289; CHECK-NEXT: [[TMP18:%.*]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], splat (i64 1)1290; CHECK-NEXT: [[TMP19:%.*]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], splat (i64 2)1291; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i16, ptr [[A]], <vscale x 4 x i64> [[TMP18]]1292; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i16> @llvm.masked.gather.nxv4i16.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP20]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i16> poison), !alias.scope [[META34:![0-9]+]]1293; CHECK-NEXT: [[TMP21:%.*]] = sext <vscale x 4 x i16> [[WIDE_MASKED_GATHER]] to <vscale x 4 x i32>1294; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds i16, ptr [[A]], <vscale x 4 x i64> [[TMP19]]1295; CHECK-NEXT: [[WIDE_MASKED_GATHER4]] = call <vscale x 4 x i16> @llvm.masked.gather.nxv4i16.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP22]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i16> poison), !alias.scope [[META34]]1296; CHECK-NEXT: [[TMP23:%.*]] = call <vscale x 4 x i16> @llvm.vector.splice.nxv4i16(<vscale x 4 x i16> [[VECTOR_RECUR]], <vscale x 4 x i16> [[WIDE_MASKED_GATHER4]], i32 -1)1297; CHECK-NEXT: [[TMP24:%.*]] = sext <vscale x 4 x i16> [[TMP23]] to <vscale x 4 x i32>1298; CHECK-NEXT: [[TMP25:%.*]] = sext <vscale x 4 x i16> [[WIDE_MASKED_GATHER4]] to <vscale x 4 x i32>1299; CHECK-NEXT: [[TMP26:%.*]] = mul nsw <vscale x 4 x i32> [[TMP24]], [[TMP21]]1300; CHECK-NEXT: [[TMP27:%.*]] = mul nsw <vscale x 4 x i32> [[TMP26]], [[TMP25]]1301; CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]]1302; CHECK-NEXT: store <vscale x 4 x i32> [[TMP27]], ptr [[TMP28]], align 4, !alias.scope [[META37:![0-9]+]], !noalias [[META34]]1303; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP10]]1304; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]1305; CHECK-NEXT: [[TMP29:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]1306; CHECK-NEXT: br i1 [[TMP29]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP39:![0-9]+]]1307; CHECK: middle.block:1308; CHECK-NEXT: [[TMP30:%.*]] = call i32 @llvm.vscale.i32()1309; CHECK-NEXT: [[TMP31:%.*]] = shl nuw nsw i32 [[TMP30]], 21310; CHECK-NEXT: [[TMP32:%.*]] = add nsw i32 [[TMP31]], -11311; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <vscale x 4 x i16> [[WIDE_MASKED_GATHER4]], i32 [[TMP32]]1312; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP1]], [[N_VEC]]1313; CHECK-NEXT: br i1 [[CMP_N]], label [[END:%.*]], label [[SCALAR_PH]]1314; CHECK: scalar.ph:1315;1316entry:1317 %.pre = load i16, ptr %a1318 br label %loop1319 1320loop:1321 %0 = phi i16 [ %.pre, %entry ], [ %load2, %loop ]1322 %iv = phi i64 [ 0, %entry ], [ %iv2, %loop ]1323 %i = phi i64 [ 0, %entry ], [ %i1, %loop ]1324 %conv = sext i16 %0 to i321325 %i1 = add nuw nsw i64 %i, 11326 %iv1 = add nuw nsw i64 %iv, 11327 %iv2 = add nuw nsw i64 %iv, 21328 %gep1 = getelementptr inbounds i16, ptr %a, i64 %iv11329 %load1 = load i16, ptr %gep1, align 41330 %conv1 = sext i16 %load1 to i321331 %gep2 = getelementptr inbounds i16, ptr %a, i64 %iv21332 %load2 = load i16, ptr %gep2, align 41333 %conv2 = sext i16 %load2 to i321334 %mul01 = mul nsw i32 %conv, %conv11335 %mul012 = mul nsw i32 %mul01, %conv21336 %arrayidx5 = getelementptr inbounds i32, ptr %b, i64 %i1337 store i32 %mul012, ptr %arrayidx51338 %exitcond = icmp eq i64 %iv, %n1339 br i1 %exitcond, label %end, label %loop1340 1341end:1342 ret void1343}1344 1345; Check vectorization on an interleaved load/store groups of factor 31346 1347; for (int i = 0; i < 1024; ++i) {1348; dst[i].x = a[i].x + b[i].x;1349; dst[i].y = a[i].y - b[i].y;1350; dst[i].z = a[i].z << b[i].z;1351; }1352;1353; TODO: Support scalable interleave groups once we can also codegen1354; @llvm.[de]interleave31355%struct.xyz = type { i32, i32, i32 }1356 1357define void @interleave_deinterleave_factor3(ptr writeonly noalias %dst, ptr readonly %a, ptr readonly %b) {1358; CHECK-LABEL: @interleave_deinterleave_factor3(1359; CHECK-NEXT: entry:1360; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()1361; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ugt i64 [[TMP0]], 2561362; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]1363; CHECK: vector.ph:1364; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()1365; CHECK-NEXT: [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 21366; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP3]]1367; CHECK-NEXT: [[N_VEC:%.*]] = sub nuw nsw i64 1024, [[N_MOD_VF]]1368; CHECK-NEXT: [[TMP6:%.*]] = call <vscale x 4 x i64> @llvm.stepvector.nxv4i64()1369; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP3]], i64 01370; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer1371; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1372; CHECK: vector.body:1373; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1374; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[TMP6]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]1375; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT_XYZ:%.*]], ptr [[A:%.*]], <vscale x 4 x i64> [[VEC_IND]]1376; CHECK-NEXT: [[TMP7:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP19]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)1377; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_XYZ]], ptr [[B:%.*]], <vscale x 4 x i64> [[VEC_IND]]1378; CHECK-NEXT: [[TMP11:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP20]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)1379; CHECK-NEXT: [[TMP14:%.*]] = add nsw <vscale x 4 x i32> [[TMP11]], [[TMP7]]1380; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_XYZ]], ptr [[DST:%.*]], <vscale x 4 x i64> [[VEC_IND]]1381; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP14]], <vscale x 4 x ptr> align 4 [[TMP10]], <vscale x 4 x i1> splat (i1 true))1382; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw i8, <vscale x 4 x ptr> [[TMP19]], i64 41383; CHECK-NEXT: [[TMP8:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP21]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)1384; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw i8, <vscale x 4 x ptr> [[TMP20]], i64 41385; CHECK-NEXT: [[TMP12:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP22]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)1386; CHECK-NEXT: [[TMP16:%.*]] = sub nsw <vscale x 4 x i32> [[TMP8]], [[TMP12]]1387; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw i8, <vscale x 4 x ptr> [[TMP10]], i64 41388; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP16]], <vscale x 4 x ptr> align 4 [[TMP23]], <vscale x 4 x i1> splat (i1 true))1389; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw i8, <vscale x 4 x ptr> [[TMP19]], i64 81390; CHECK-NEXT: [[TMP9:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP15]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)1391; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw i8, <vscale x 4 x ptr> [[TMP20]], i64 81392; CHECK-NEXT: [[TMP13:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> align 4 [[TMP24]], <vscale x 4 x i1> splat (i1 true), <vscale x 4 x i32> poison)1393; CHECK-NEXT: [[TMP17:%.*]] = shl <vscale x 4 x i32> [[TMP9]], [[TMP13]]1394; CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw i8, <vscale x 4 x ptr> [[TMP10]], i64 81395; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[TMP17]], <vscale x 4 x ptr> align 4 [[TMP25]], <vscale x 4 x i1> splat (i1 true))1396; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP3]]1397; CHECK-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]]1398; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]1399; CHECK-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP41:![0-9]+]]1400; CHECK: middle.block:1401; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N_MOD_VF]], 01402; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]]1403; CHECK: scalar.ph:1404;1405entry:1406 br label %for.body1407 1408for.body:1409 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]1410 %arrayidx = getelementptr inbounds %struct.xyz, ptr %a, i64 %indvars.iv1411 %0 = load i32, ptr %arrayidx, align 41412 %arrayidx2 = getelementptr inbounds %struct.xyz, ptr %b, i64 %indvars.iv1413 %1 = load i32, ptr %arrayidx2, align 41414 %add = add nsw i32 %1, %01415 %arrayidx5 = getelementptr inbounds %struct.xyz, ptr %dst, i64 %indvars.iv1416 store i32 %add, ptr %arrayidx5, align 41417 %y = getelementptr inbounds nuw i8, ptr %arrayidx, i64 41418 %2 = load i32, ptr %y, align 41419 %y11 = getelementptr inbounds nuw i8, ptr %arrayidx2, i64 41420 %3 = load i32, ptr %y11, align 41421 %sub = sub nsw i32 %2, %31422 %y14 = getelementptr inbounds nuw i8, ptr %arrayidx5, i64 41423 store i32 %sub, ptr %y14, align 41424 %z = getelementptr inbounds nuw i8, ptr %arrayidx, i64 81425 %4 = load i32, ptr %z, align 41426 %z19 = getelementptr inbounds nuw i8, ptr %arrayidx2, i64 81427 %5 = load i32, ptr %z19, align 41428 %shl = shl i32 %4, %51429 %z22 = getelementptr inbounds nuw i8, ptr %arrayidx5, i64 81430 store i32 %shl, ptr %z22, align 41431 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 11432 %exitcond.not = icmp eq i64 %indvars.iv.next, 10241433 br i1 %exitcond.not, label %for.end, label %for.body1434 1435for.end:1436 ret void1437}1438 1439; Check vectorization on an interleaved load/store groups of factor 41440 1441; for (int i = 0; i < 1024; ++i) {1442; dst[i].x = a[i].x + b[i].x;1443; dst[i].y = a[i].y - b[i].y;1444; dst[i].z = a[i].z << b[i].z;1445; dst[i].t = a[i].t >> b[i].t;1446; }1447%struct.xyzt = type { i32, i32, i32, i32 }1448 1449define void @interleave_deinterleave(ptr writeonly noalias %dst, ptr readonly %a, ptr readonly %b) {1450; CHECK-LABEL: @interleave_deinterleave(1451; CHECK-NEXT: entry:1452; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()1453; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ugt i64 [[TMP0]], 2561454; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]1455; CHECK: vector.ph:1456; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()1457; CHECK-NEXT: [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 21458; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP3]]1459; CHECK-NEXT: [[N_VEC:%.*]] = sub nuw nsw i64 1024, [[N_MOD_VF]]1460; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1461; CHECK: vector.body:1462; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1463; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_XYZT:%.*]], ptr [[A:%.*]], i64 [[INDEX]]1464; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 16 x i32>, ptr [[TMP6]], align 41465; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave4.nxv16i32(<vscale x 16 x i32> [[WIDE_VEC]])1466; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 01467; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 11468; CHECK-NEXT: [[TMP11:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 21469; CHECK-NEXT: [[TMP12:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 31470; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_XYZT]], ptr [[B:%.*]], i64 [[INDEX]]1471; CHECK-NEXT: [[WIDE_VEC8:%.*]] = load <vscale x 16 x i32>, ptr [[TMP13]], align 41472; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave4.nxv16i32(<vscale x 16 x i32> [[WIDE_VEC8]])1473; CHECK-NEXT: [[TMP16:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 01474; CHECK-NEXT: [[TMP17:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 11475; CHECK-NEXT: [[TMP18:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 21476; CHECK-NEXT: [[TMP19:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC2]], 31477; CHECK-NEXT: [[TMP20:%.*]] = add nsw <vscale x 4 x i32> [[TMP16]], [[TMP9]]1478; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT_XYZT]], ptr [[DST:%.*]], i64 [[INDEX]]1479; CHECK-NEXT: [[TMP22:%.*]] = sub nsw <vscale x 4 x i32> [[TMP10]], [[TMP17]]1480; CHECK-NEXT: [[TMP23:%.*]] = shl <vscale x 4 x i32> [[TMP11]], [[TMP18]]1481; CHECK-NEXT: [[TMP24:%.*]] = ashr <vscale x 4 x i32> [[TMP12]], [[TMP19]]1482; CHECK-NEXT: [[INTERLEAVED_VEC13:%.*]] = call <vscale x 16 x i32> @llvm.vector.interleave4.nxv16i32(<vscale x 4 x i32> [[TMP20]], <vscale x 4 x i32> [[TMP22]], <vscale x 4 x i32> [[TMP23]], <vscale x 4 x i32> [[TMP24]])1483; CHECK-NEXT: store <vscale x 16 x i32> [[INTERLEAVED_VEC13]], ptr [[TMP21]], align 41484; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP3]]1485; CHECK-NEXT: [[TMP25:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]1486; CHECK-NEXT: br i1 [[TMP25]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP43:![0-9]+]]1487; CHECK: middle.block:1488; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N_MOD_VF]], 01489; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]]1490; CHECK: scalar.ph:1491;1492entry:1493 br label %for.body1494 1495for.body:1496 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]1497 %arrayidx = getelementptr inbounds %struct.xyzt, ptr %a, i64 %indvars.iv1498 %0 = load i32, ptr %arrayidx, align 41499 %arrayidx2 = getelementptr inbounds %struct.xyzt, ptr %b, i64 %indvars.iv1500 %1 = load i32, ptr %arrayidx2, align 41501 %add = add nsw i32 %1, %01502 %arrayidx5 = getelementptr inbounds %struct.xyzt, ptr %dst, i64 %indvars.iv1503 store i32 %add, ptr %arrayidx5, align 41504 %y = getelementptr inbounds nuw i8, ptr %arrayidx, i64 41505 %2 = load i32, ptr %y, align 41506 %y11 = getelementptr inbounds nuw i8, ptr %arrayidx2, i64 41507 %3 = load i32, ptr %y11, align 41508 %sub = sub nsw i32 %2, %31509 %y14 = getelementptr inbounds nuw i8, ptr %arrayidx5, i64 41510 store i32 %sub, ptr %y14, align 41511 %z = getelementptr inbounds nuw i8, ptr %arrayidx, i64 81512 %4 = load i32, ptr %z, align 41513 %z19 = getelementptr inbounds nuw i8, ptr %arrayidx2, i64 81514 %5 = load i32, ptr %z19, align 41515 %shl = shl i32 %4, %51516 %z22 = getelementptr inbounds nuw i8, ptr %arrayidx5, i64 81517 store i32 %shl, ptr %z22, align 41518 %t = getelementptr inbounds nuw i8, ptr %arrayidx, i64 121519 %6 = load i32, ptr %t, align 41520 %t27 = getelementptr inbounds nuw i8, ptr %arrayidx2, i64 121521 %7 = load i32, ptr %t27, align 41522 %shr = ashr i32 %6, %71523 %t30 = getelementptr inbounds nuw i8, ptr %arrayidx5, i64 121524 store i32 %shr, ptr %t30, align 41525 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 11526 %exitcond.not = icmp eq i64 %indvars.iv.next, 10241527 br i1 %exitcond.not, label %for.end, label %for.body1528 1529for.end:1530 ret void1531}1532 1533; Check vectorization on a reverse interleaved load/store groups of factor 41534 1535; for (int i = 1023; i >= 0; i--) {1536; int a = A[i].x + i;1537; int b = A[i].y - i;1538; int c = A[i].z * i;1539; int d = A[i].t << i;1540; B[i].x = a;1541; B[i].y = b;1542; B[i].z = c;1543; B[i].t = d;1544; }1545 1546define void @interleave_deinterleave_reverse(ptr noalias nocapture readonly %A, ptr noalias nocapture %B) #1{1547; CHECK-LABEL: @interleave_deinterleave_reverse(1548; CHECK-NEXT: entry:1549; CHECK-NEXT: br label [[VECTOR_PH:%.*]]1550; CHECK: vector.ph:1551; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()1552; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 21553; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i32> @llvm.stepvector.nxv4i32()1554; CHECK-NEXT: [[INDUCTION:%.*]] = sub <vscale x 4 x i32> splat (i32 1023), [[TMP2]]1555; CHECK-NEXT: [[TMP3:%.*]] = trunc nuw nsw i64 [[TMP1]] to i321556; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 0, [[TMP3]]1557; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[TMP4]], i64 01558; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[DOTSPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer1559; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]1560; CHECK: vector.body:1561; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]1562; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i32> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]1563; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i64 1023, [[INDEX]]1564; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_XYZT:%.*]], ptr [[A:%.*]], i64 [[OFFSET_IDX]]1565; CHECK-NEXT: [[TMP6:%.*]] = shl nuw nsw i64 [[TMP0]], 41566; CHECK-NEXT: [[TMP9:%.*]] = sub nsw i64 4, [[TMP6]]1567; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i64 [[TMP9]]1568; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 16 x i32>, ptr [[TMP10]], align 41569; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave4.nxv16i32(<vscale x 16 x i32> [[WIDE_VEC]])1570; CHECK-NEXT: [[TMP13:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 01571; CHECK-NEXT: [[REVERSE:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP13]])1572; CHECK-NEXT: [[TMP14:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 11573; CHECK-NEXT: [[REVERSE3:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP14]])1574; CHECK-NEXT: [[TMP15:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 21575; CHECK-NEXT: [[REVERSE4:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP15]])1576; CHECK-NEXT: [[TMP16:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 31577; CHECK-NEXT: [[REVERSE5:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP16]])1578; CHECK-NEXT: [[TMP17:%.*]] = add nsw <vscale x 4 x i32> [[REVERSE]], [[VEC_IND]]1579; CHECK-NEXT: [[TMP18:%.*]] = sub nsw <vscale x 4 x i32> [[REVERSE3]], [[VEC_IND]]1580; CHECK-NEXT: [[TMP19:%.*]] = mul nsw <vscale x 4 x i32> [[REVERSE4]], [[VEC_IND]]1581; CHECK-NEXT: [[TMP20:%.*]] = shl nuw nsw <vscale x 4 x i32> [[REVERSE5]], [[VEC_IND]]1582; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT_XYZT]], ptr [[B:%.*]], i64 [[OFFSET_IDX]]1583; CHECK-NEXT: [[TMP22:%.*]] = shl nuw nsw i64 [[TMP0]], 41584; CHECK-NEXT: [[TMP25:%.*]] = sub nsw i64 4, [[TMP22]]1585; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds i32, ptr [[TMP21]], i64 [[TMP25]]1586; CHECK-NEXT: [[REVERSE6:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP17]])1587; CHECK-NEXT: [[REVERSE7:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP18]])1588; CHECK-NEXT: [[REVERSE8:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP19]])1589; CHECK-NEXT: [[REVERSE9:%.*]] = call <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> [[TMP20]])1590; CHECK-NEXT: [[INTERLEAVED_VEC11:%.*]] = call <vscale x 16 x i32> @llvm.vector.interleave4.nxv16i32(<vscale x 4 x i32> [[REVERSE6]], <vscale x 4 x i32> [[REVERSE7]], <vscale x 4 x i32> [[REVERSE8]], <vscale x 4 x i32> [[REVERSE9]])1591; CHECK-NEXT: store <vscale x 16 x i32> [[INTERLEAVED_VEC11]], ptr [[TMP26]], align 41592; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]1593; CHECK-NEXT: [[VEC_IND_NEXT]] = add <vscale x 4 x i32> [[VEC_IND]], [[DOTSPLAT]]1594; CHECK-NEXT: [[TMP27:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10241595; CHECK-NEXT: br i1 [[TMP27]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP45:![0-9]+]]1596; CHECK: middle.block:1597; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH:%.*]]1598; CHECK: scalar.ph:1599;1600entry:1601 br label %for.body1602for.cond.cleanup: ; preds = %for.body1603 ret void1604for.body: ; preds = %for.body, %entry1605 %indvars.iv = phi i64 [ 1023, %entry ], [ %indvars.iv.next, %for.body ]1606 %x = getelementptr inbounds %struct.xyzt, ptr %A, i64 %indvars.iv, i32 01607 %load1 = load i32, ptr %x, align 41608 %trunc = trunc i64 %indvars.iv to i321609 %add = add nsw i32 %load1, %trunc1610 %y = getelementptr inbounds %struct.xyzt, ptr %A, i64 %indvars.iv, i32 11611 %load2 = load i32, ptr %y, align 41612 %sub = sub nsw i32 %load2, %trunc1613 %z = getelementptr inbounds %struct.xyzt, ptr %A, i64 %indvars.iv, i32 21614 %load3 = load i32, ptr %z, align 41615 %mul = mul nsw i32 %load3, %trunc1616 %t = getelementptr inbounds %struct.xyzt, ptr %A, i64 %indvars.iv, i32 31617 %load4 = load i32, ptr %t, align 41618 %shl = shl nuw nsw i32 %load4, %trunc1619 %x5 = getelementptr inbounds %struct.xyzt, ptr %B, i64 %indvars.iv, i32 01620 store i32 %add, ptr %x5, align 41621 %y8 = getelementptr inbounds %struct.xyzt, ptr %B, i64 %indvars.iv, i32 11622 store i32 %sub, ptr %y8, align 41623 %z5 = getelementptr inbounds %struct.xyzt, ptr %B, i64 %indvars.iv, i32 21624 store i32 %mul, ptr %z5, align 41625 %t8 = getelementptr inbounds %struct.xyzt, ptr %B, i64 %indvars.iv, i32 31626 store i32 %shl, ptr %t8, align 41627 %indvars.iv.next = add nsw i64 %indvars.iv, -11628 %cmp = icmp sgt i64 %indvars.iv, 01629 br i1 %cmp, label %for.body, label %for.cond.cleanup1630 1631}1632attributes #1 = { "target-features"="+sve" vscale_range(1, 16) }1633attributes #0 = { "target-features"="+sve" vscale_range(1, 16) }1634