1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -hints-allow-reordering=false -loop-vectorize -prefer-predicate-over-epilogue=predicate-else-scalar-epilogue < %s | FileCheck %s 3 4target triple = "aarch64-unknown-linux-gnu" 5 6 7define void @simple_memset(i32 %val, i32* %ptr, i64 %n) #0 { 8; CHECK-LABEL: @simple_memset( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 1) 11; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[UMAX]] 12; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 13; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 14; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 15; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 16; CHECK: vector.ph: 17; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 18; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 19; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 20; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 21; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 22; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[UMAX]], [[TMP8]] 23; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 24; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 25; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[UMAX]]) 26; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[VAL:%.*]], i32 0 27; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer 28; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 29; CHECK: vector.body: 30; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VECTOR_BODY]] ] 31; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 32; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX1]], 0 33; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i64 [[TMP9]] 34; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i32, i32* [[TMP10]], i32 0 35; CHECK-NEXT: [[TMP12:%.*]] = bitcast i32* [[TMP11]] to <vscale x 4 x i32>* 36; CHECK-NEXT: call void @llvm.masked.store.nxv4i32.p0nxv4i32(<vscale x 4 x i32> [[BROADCAST_SPLAT]], <vscale x 4 x i32>* [[TMP12]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 37; CHECK-NEXT: [[TMP13:%.*]] = call i64 @llvm.vscale.i64() 38; CHECK-NEXT: [[TMP14:%.*]] = mul i64 [[TMP13]], 4 39; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], [[TMP14]] 40; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT2]], i64 [[UMAX]]) 41; CHECK-NEXT: [[TMP15:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 42; CHECK-NEXT: [[TMP16:%.*]] = extractelement <vscale x 4 x i1> [[TMP15]], i32 0 43; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 44; CHECK: middle.block: 45; CHECK-NEXT: br i1 true, label [[WHILE_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] 46; CHECK: scalar.ph: 47; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 48; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 49; CHECK: while.body: 50; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 51; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[PTR]], i64 [[INDEX]] 52; CHECK-NEXT: store i32 [[VAL]], i32* [[GEP]], align 4 53; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 1 54; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N]] 55; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT]], !llvm.loop [[LOOP2:![0-9]+]] 56; CHECK: while.end.loopexit: 57; CHECK-NEXT: ret void 58; 59entry: 60 br label %while.body 61 62while.body: ; preds = %while.body, %entry 63 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 64 %gep = getelementptr i32, i32* %ptr, i64 %index 65 store i32 %val, i32* %gep 66 %index.next = add nsw i64 %index, 1 67 %cmp10 = icmp ult i64 %index.next, %n 68 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !0 69 70while.end.loopexit: ; preds = %while.body 71 ret void 72} 73 74 75define void @simple_memset_v4i32(i32 %val, i32* %ptr, i64 %n) #0 { 76; CHECK-LABEL: @simple_memset_v4i32( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 1) 79; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 80; CHECK: vector.ph: 81; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[UMAX]], 3 82; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], 4 83; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 84; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i64(i64 0, i64 [[UMAX]]) 85; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i32> poison, i32 [[VAL:%.*]], i32 0 86; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT]], <4 x i32> poison, <4 x i32> zeroinitializer 87; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 88; CHECK: vector.body: 89; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VECTOR_BODY]] ] 90; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 91; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX1]], 0 92; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i64 [[TMP0]] 93; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], i32 0 94; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* 95; CHECK-NEXT: call void @llvm.masked.store.v4i32.p0v4i32(<4 x i32> [[BROADCAST_SPLAT]], <4 x i32>* [[TMP3]], i32 4, <4 x i1> [[ACTIVE_LANE_MASK]]) 96; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], 4 97; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i64(i64 [[INDEX_NEXT2]], i64 [[UMAX]]) 98; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i1> [[ACTIVE_LANE_MASK_NEXT]], <i1 true, i1 true, i1 true, i1 true> 99; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i1> [[TMP4]], i32 0 100; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] 101; CHECK: middle.block: 102; CHECK-NEXT: br i1 true, label [[WHILE_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] 103; CHECK: scalar.ph: 104; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 105; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 106; CHECK: while.body: 107; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 108; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[PTR]], i64 [[INDEX]] 109; CHECK-NEXT: store i32 [[VAL]], i32* [[GEP]], align 4 110; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 1 111; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N]] 112; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT]], !llvm.loop [[LOOP5:![0-9]+]] 113; CHECK: while.end.loopexit: 114; CHECK-NEXT: ret void 115; 116entry: 117 br label %while.body 118 119while.body: ; preds = %while.body, %entry 120 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 121 %gep = getelementptr i32, i32* %ptr, i64 %index 122 store i32 %val, i32* %gep 123 %index.next = add nsw i64 %index, 1 124 %cmp10 = icmp ult i64 %index.next, %n 125 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !3 126 127while.end.loopexit: ; preds = %while.body 128 ret void 129} 130 131 132define void @simple_memcpy(i32* noalias %dst, i32* noalias %src, i64 %n) #0 { 133; CHECK-LABEL: @simple_memcpy( 134; CHECK-NEXT: entry: 135; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 1) 136; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[UMAX]] 137; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 138; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 139; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 140; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 141; CHECK: vector.ph: 142; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 143; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 144; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 145; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 146; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 147; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[UMAX]], [[TMP8]] 148; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 149; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 150; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[UMAX]]) 151; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 152; CHECK: vector.body: 153; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VECTOR_BODY]] ] 154; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 155; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX1]], 0 156; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, i32* [[SRC:%.*]], i64 [[TMP9]] 157; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i32, i32* [[TMP10]], i32 0 158; CHECK-NEXT: [[TMP12:%.*]] = bitcast i32* [[TMP11]] to <vscale x 4 x i32>* 159; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <vscale x 4 x i32> @llvm.masked.load.nxv4i32.p0nxv4i32(<vscale x 4 x i32>* [[TMP12]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i32> poison) 160; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[TMP9]] 161; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, i32* [[TMP13]], i32 0 162; CHECK-NEXT: [[TMP15:%.*]] = bitcast i32* [[TMP14]] to <vscale x 4 x i32>* 163; CHECK-NEXT: call void @llvm.masked.store.nxv4i32.p0nxv4i32(<vscale x 4 x i32> [[WIDE_MASKED_LOAD]], <vscale x 4 x i32>* [[TMP15]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 164; CHECK-NEXT: [[TMP16:%.*]] = call i64 @llvm.vscale.i64() 165; CHECK-NEXT: [[TMP17:%.*]] = mul i64 [[TMP16]], 4 166; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], [[TMP17]] 167; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT2]], i64 [[UMAX]]) 168; CHECK-NEXT: [[TMP18:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 169; CHECK-NEXT: [[TMP19:%.*]] = extractelement <vscale x 4 x i1> [[TMP18]], i32 0 170; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] 171; CHECK: middle.block: 172; CHECK-NEXT: br i1 true, label [[WHILE_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] 173; CHECK: scalar.ph: 174; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 175; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 176; CHECK: while.body: 177; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 178; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, i32* [[SRC]], i64 [[INDEX]] 179; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[GEP1]], align 4 180; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, i32* [[DST]], i64 [[INDEX]] 181; CHECK-NEXT: store i32 [[VAL]], i32* [[GEP2]], align 4 182; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 1 183; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N]] 184; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]] 185; CHECK: while.end.loopexit: 186; CHECK-NEXT: ret void 187; 188entry: 189 br label %while.body 190 191while.body: ; preds = %while.body, %entry 192 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 193 %gep1 = getelementptr i32, i32* %src, i64 %index 194 %val = load i32, i32* %gep1 195 %gep2 = getelementptr i32, i32* %dst, i64 %index 196 store i32 %val, i32* %gep2 197 %index.next = add nsw i64 %index, 1 198 %cmp10 = icmp ult i64 %index.next, %n 199 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !0 200 201while.end.loopexit: ; preds = %while.body 202 ret void 203} 204 205 206define void @copy_stride4(i32* noalias %dst, i32* noalias %src, i64 %n) #0 { 207; CHECK-LABEL: @copy_stride4( 208; CHECK-NEXT: entry: 209; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 4) 210; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[UMAX]], -1 211; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 2 212; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 213; CHECK-NEXT: [[TMP3:%.*]] = sub i64 -1, [[TMP2]] 214; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 215; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 216; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i64 [[TMP3]], [[TMP5]] 217; CHECK-NEXT: br i1 [[TMP6]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 218; CHECK: vector.ph: 219; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.vscale.i64() 220; CHECK-NEXT: [[TMP8:%.*]] = mul i64 [[TMP7]], 4 221; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() 222; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 4 223; CHECK-NEXT: [[TMP11:%.*]] = sub i64 [[TMP10]], 1 224; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[TMP2]], [[TMP11]] 225; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP8]] 226; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 227; CHECK-NEXT: [[IND_END:%.*]] = mul i64 [[N_VEC]], 4 228; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[TMP2]]) 229; CHECK-NEXT: [[TMP12:%.*]] = call <vscale x 4 x i64> @llvm.experimental.stepvector.nxv4i64() 230; CHECK-NEXT: [[TMP13:%.*]] = add <vscale x 4 x i64> [[TMP12]], zeroinitializer 231; CHECK-NEXT: [[TMP14:%.*]] = mul <vscale x 4 x i64> [[TMP13]], shufflevector (<vscale x 4 x i64> insertelement (<vscale x 4 x i64> poison, i64 4, i32 0), <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer) 232; CHECK-NEXT: [[INDUCTION:%.*]] = add <vscale x 4 x i64> zeroinitializer, [[TMP14]] 233; CHECK-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() 234; CHECK-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 4 235; CHECK-NEXT: [[TMP17:%.*]] = mul i64 4, [[TMP16]] 236; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 4 x i64> poison, i64 [[TMP17]], i32 0 237; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 4 x i64> [[DOTSPLATINSERT]], <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer 238; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 239; CHECK: vector.body: 240; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VECTOR_BODY]] ] 241; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 242; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 4 x i64> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] 243; CHECK-NEXT: [[TMP18:%.*]] = getelementptr i32, i32* [[SRC:%.*]], <vscale x 4 x i64> [[VEC_IND]] 244; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP18]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i32> undef) 245; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i32, i32* [[DST:%.*]], <vscale x 4 x i64> [[VEC_IND]] 246; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> [[WIDE_MASKED_GATHER]], <vscale x 4 x i32*> [[TMP19]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 247; CHECK-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() 248; CHECK-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 4 249; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], [[TMP21]] 250; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT2]], i64 [[TMP2]]) 251; CHECK-NEXT: [[TMP22:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 252; CHECK-NEXT: [[VEC_IND_NEXT]] = add <vscale x 4 x i64> [[VEC_IND]], [[DOTSPLAT]] 253; CHECK-NEXT: [[TMP23:%.*]] = extractelement <vscale x 4 x i1> [[TMP22]], i32 0 254; CHECK-NEXT: br i1 [[TMP23]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] 255; CHECK: middle.block: 256; CHECK-NEXT: br i1 true, label [[WHILE_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] 257; CHECK: scalar.ph: 258; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 259; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 260; CHECK: while.body: 261; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 262; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, i32* [[SRC]], i64 [[INDEX]] 263; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[GEP1]], align 4 264; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, i32* [[DST]], i64 [[INDEX]] 265; CHECK-NEXT: store i32 [[VAL]], i32* [[GEP2]], align 4 266; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 4 267; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N]] 268; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT]], !llvm.loop [[LOOP9:![0-9]+]] 269; CHECK: while.end.loopexit: 270; CHECK-NEXT: ret void 271; 272entry: 273 br label %while.body 274 275while.body: ; preds = %while.body, %entry 276 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 277 %gep1 = getelementptr i32, i32* %src, i64 %index 278 %val = load i32, i32* %gep1 279 %gep2 = getelementptr i32, i32* %dst, i64 %index 280 store i32 %val, i32* %gep2 281 %index.next = add nsw i64 %index, 4 282 %cmp10 = icmp ult i64 %index.next, %n 283 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !0 284 285while.end.loopexit: ; preds = %while.body 286 ret void 287} 288 289 290define void @simple_gather_scatter(i32* noalias %dst, i32* noalias %src, i32* noalias %ind, i64 %n) #0 { 291; CHECK-LABEL: @simple_gather_scatter( 292; CHECK-NEXT: entry: 293; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 1) 294; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[UMAX]] 295; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 296; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 297; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 298; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 299; CHECK: vector.ph: 300; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 301; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 302; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 303; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 304; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 305; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[UMAX]], [[TMP8]] 306; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 307; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 308; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[UMAX]]) 309; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 310; CHECK: vector.body: 311; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VECTOR_BODY]] ] 312; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 313; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX1]], 0 314; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, i32* [[IND:%.*]], i64 [[TMP9]] 315; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i32, i32* [[TMP10]], i32 0 316; CHECK-NEXT: [[TMP12:%.*]] = bitcast i32* [[TMP11]] to <vscale x 4 x i32>* 317; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <vscale x 4 x i32> @llvm.masked.load.nxv4i32.p0nxv4i32(<vscale x 4 x i32>* [[TMP12]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i32> poison) 318; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i32, i32* [[SRC:%.*]], <vscale x 4 x i32> [[WIDE_MASKED_LOAD]] 319; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP13]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i32> undef) 320; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i32, i32* [[DST:%.*]], <vscale x 4 x i32> [[WIDE_MASKED_LOAD]] 321; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> [[WIDE_MASKED_GATHER]], <vscale x 4 x i32*> [[TMP14]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 322; CHECK-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() 323; CHECK-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 4 324; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], [[TMP16]] 325; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT2]], i64 [[UMAX]]) 326; CHECK-NEXT: [[TMP17:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 327; CHECK-NEXT: [[TMP18:%.*]] = extractelement <vscale x 4 x i1> [[TMP17]], i32 0 328; CHECK-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] 329; CHECK: middle.block: 330; CHECK-NEXT: br i1 true, label [[WHILE_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] 331; CHECK: scalar.ph: 332; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 333; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 334; CHECK: while.body: 335; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 336; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, i32* [[IND]], i64 [[INDEX]] 337; CHECK-NEXT: [[IND_VAL:%.*]] = load i32, i32* [[GEP1]], align 4 338; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, i32* [[SRC]], i32 [[IND_VAL]] 339; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[GEP2]], align 4 340; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i32, i32* [[DST]], i32 [[IND_VAL]] 341; CHECK-NEXT: store i32 [[VAL]], i32* [[GEP3]], align 4 342; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 1 343; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N]] 344; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT]], !llvm.loop [[LOOP11:![0-9]+]] 345; CHECK: while.end.loopexit: 346; CHECK-NEXT: ret void 347; 348entry: 349 br label %while.body 350 351while.body: ; preds = %while.body, %entry 352 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 353 %gep1 = getelementptr i32, i32* %ind, i64 %index 354 %ind_val = load i32, i32* %gep1 355 %gep2 = getelementptr i32, i32* %src, i32 %ind_val 356 %val = load i32, i32* %gep2 357 %gep3 = getelementptr i32, i32* %dst, i32 %ind_val 358 store i32 %val, i32* %gep3 359 %index.next = add nsw i64 %index, 1 360 %cmp10 = icmp ult i64 %index.next, %n 361 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !0 362 363while.end.loopexit: ; preds = %while.body 364 ret void 365} 366 367 368; The original loop had an unconditional uniform load. Let's make sure 369; we don't artificially create new predicated blocks for the load. 370define void @uniform_load(i32* noalias %dst, i32* noalias readonly %src, i64 %n) #0 { 371; CHECK-LABEL: @uniform_load( 372; CHECK-NEXT: entry: 373; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[N:%.*]] 374; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 375; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 376; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 377; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 378; CHECK: vector.ph: 379; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 380; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 381; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 382; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 383; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 384; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[N]], [[TMP8]] 385; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 386; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 387; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[N]]) 388; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 389; CHECK: vector.body: 390; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 391; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 392; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX]], 0 393; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[SRC:%.*]], align 4 394; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[TMP10]], i32 0 395; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer 396; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i32, i32* [[DST:%.*]], i64 [[TMP9]] 397; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[TMP11]], i32 0 398; CHECK-NEXT: [[TMP13:%.*]] = bitcast i32* [[TMP12]] to <vscale x 4 x i32>* 399; CHECK-NEXT: call void @llvm.masked.store.nxv4i32.p0nxv4i32(<vscale x 4 x i32> [[BROADCAST_SPLAT]], <vscale x 4 x i32>* [[TMP13]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 400; CHECK-NEXT: [[TMP14:%.*]] = call i64 @llvm.vscale.i64() 401; CHECK-NEXT: [[TMP15:%.*]] = mul i64 [[TMP14]], 4 402; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP15]] 403; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT]], i64 [[N]]) 404; CHECK-NEXT: [[TMP16:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 405; CHECK-NEXT: [[TMP17:%.*]] = extractelement <vscale x 4 x i1> [[TMP16]], i32 0 406; CHECK-NEXT: br i1 [[TMP17]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] 407; CHECK: middle.block: 408; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] 409; CHECK: scalar.ph: 410; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 411; CHECK-NEXT: br label [[FOR_BODY:%.*]] 412; CHECK: for.body: 413; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 414; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[SRC]], align 4 415; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DST]], i64 [[INDVARS_IV]] 416; CHECK-NEXT: store i32 [[VAL]], i32* [[ARRAYIDX]], align 4 417; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 418; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[N]] 419; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP13:![0-9]+]] 420; CHECK: for.end: 421; CHECK-NEXT: ret void 422; 423 424entry: 425 br label %for.body 426 427for.body: ; preds = %entry, %for.body 428 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 429 %val = load i32, i32* %src, align 4 430 %arrayidx = getelementptr inbounds i32, i32* %dst, i64 %indvars.iv 431 store i32 %val, i32* %arrayidx, align 4 432 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 433 %exitcond.not = icmp eq i64 %indvars.iv.next, %n 434 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 435 436for.end: ; preds = %for.body, %entry 437 ret void 438} 439 440 441; The original loop had a conditional uniform load. In this case we actually 442; do need to perform conditional loads and so we end up using a gather instead. 443; However, we at least ensure the mask is the overlap of the loop predicate 444; and the original condition. 445define void @cond_uniform_load(i32* noalias %dst, i32* noalias readonly %src, i32* noalias readonly %cond, i64 %n) #0 { 446; CHECK-LABEL: @cond_uniform_load( 447; CHECK-NEXT: entry: 448; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[N:%.*]] 449; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 450; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 451; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 452; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 453; CHECK: vector.ph: 454; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 455; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 456; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 457; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 458; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 459; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[N]], [[TMP8]] 460; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 461; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 462; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[N]]) 463; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32*> poison, i32* [[SRC:%.*]], i32 0 464; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32*> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer 465; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 466; CHECK: vector.body: 467; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VECTOR_BODY]] ] 468; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 469; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX1]], 0 470; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, i32* [[COND:%.*]], i64 [[TMP9]] 471; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i32, i32* [[TMP10]], i32 0 472; CHECK-NEXT: [[TMP12:%.*]] = bitcast i32* [[TMP11]] to <vscale x 4 x i32>* 473; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <vscale x 4 x i32> @llvm.masked.load.nxv4i32.p0nxv4i32(<vscale x 4 x i32>* [[TMP12]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i32> poison) 474; CHECK-NEXT: [[TMP13:%.*]] = icmp eq <vscale x 4 x i32> [[WIDE_MASKED_LOAD]], zeroinitializer 475; CHECK-NEXT: [[TMP14:%.*]] = xor <vscale x 4 x i1> [[TMP13]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 476; CHECK-NEXT: [[TMP15:%.*]] = select <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i1> [[TMP14]], <vscale x 4 x i1> zeroinitializer 477; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[BROADCAST_SPLAT]], i32 4, <vscale x 4 x i1> [[TMP15]], <vscale x 4 x i32> undef) 478; CHECK-NEXT: [[TMP16:%.*]] = select <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i1> [[TMP13]], <vscale x 4 x i1> zeroinitializer 479; CHECK-NEXT: [[PREDPHI:%.*]] = select <vscale x 4 x i1> [[TMP16]], <vscale x 4 x i32> zeroinitializer, <vscale x 4 x i32> [[WIDE_MASKED_GATHER]] 480; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, i32* [[DST:%.*]], i64 [[TMP9]] 481; CHECK-NEXT: [[TMP18:%.*]] = or <vscale x 4 x i1> [[TMP15]], [[TMP16]] 482; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[TMP17]], i32 0 483; CHECK-NEXT: [[TMP20:%.*]] = bitcast i32* [[TMP19]] to <vscale x 4 x i32>* 484; CHECK-NEXT: call void @llvm.masked.store.nxv4i32.p0nxv4i32(<vscale x 4 x i32> [[PREDPHI]], <vscale x 4 x i32>* [[TMP20]], i32 4, <vscale x 4 x i1> [[TMP18]]) 485; CHECK-NEXT: [[TMP21:%.*]] = call i64 @llvm.vscale.i64() 486; CHECK-NEXT: [[TMP22:%.*]] = mul i64 [[TMP21]], 4 487; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], [[TMP22]] 488; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT2]], i64 [[N]]) 489; CHECK-NEXT: [[TMP23:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 490; CHECK-NEXT: [[TMP24:%.*]] = extractelement <vscale x 4 x i1> [[TMP23]], i32 0 491; CHECK-NEXT: br i1 [[TMP24]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]] 492; CHECK: middle.block: 493; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] 494; CHECK: scalar.ph: 495; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 496; CHECK-NEXT: br label [[FOR_BODY:%.*]] 497; CHECK: for.body: 498; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[IF_END:%.*]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 499; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[COND]], i64 [[INDEX]] 500; CHECK-NEXT: [[TMP25:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 501; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP25]], 0 502; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] 503; CHECK: if.then: 504; CHECK-NEXT: [[TMP26:%.*]] = load i32, i32* [[SRC]], align 4 505; CHECK-NEXT: br label [[IF_END]] 506; CHECK: if.end: 507; CHECK-NEXT: [[VAL_0:%.*]] = phi i32 [ [[TMP26]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] 508; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[DST]], i64 [[INDEX]] 509; CHECK-NEXT: store i32 [[VAL_0]], i32* [[ARRAYIDX1]], align 4 510; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 1 511; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N]] 512; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP15:![0-9]+]] 513; CHECK: for.end: 514; CHECK-NEXT: ret void 515; 516 517entry: 518 br label %for.body 519 520for.body: ; preds = %entry, %if.end 521 %index = phi i64 [ %index.next, %if.end ], [ 0, %entry ] 522 %arrayidx = getelementptr inbounds i32, i32* %cond, i64 %index 523 %0 = load i32, i32* %arrayidx, align 4 524 %tobool.not = icmp eq i32 %0, 0 525 br i1 %tobool.not, label %if.end, label %if.then 526 527if.then: ; preds = %for.body 528 %1 = load i32, i32* %src, align 4 529 br label %if.end 530 531if.end: ; preds = %if.then, %for.body 532 %val.0 = phi i32 [ %1, %if.then ], [ 0, %for.body ] 533 %arrayidx1 = getelementptr inbounds i32, i32* %dst, i64 %index 534 store i32 %val.0, i32* %arrayidx1, align 4 535 %index.next = add nuw i64 %index, 1 536 %exitcond.not = icmp eq i64 %index.next, %n 537 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 538 539for.end: ; preds = %for.inc, %entry 540 ret void 541} 542 543 544; The original loop had an unconditional uniform store. Let's make sure 545; we don't artificially create new predicated blocks for the load. 546define void @uniform_store(i32* noalias %dst, i32* noalias readonly %src, i64 %n) #0 { 547; CHECK-LABEL: @uniform_store( 548; CHECK-NEXT: entry: 549; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[N:%.*]] 550; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 551; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 552; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 553; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 554; CHECK: vector.ph: 555; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 556; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 557; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 558; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 559; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 560; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[N]], [[TMP8]] 561; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 562; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 563; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[N]]) 564; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 4 x i32*> poison, i32* [[DST:%.*]], i32 0 565; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 4 x i32*> [[BROADCAST_SPLATINSERT]], <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer 566; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 567; CHECK: vector.body: 568; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 569; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 570; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX]], 0 571; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, i32* [[SRC:%.*]], i64 [[TMP9]] 572; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i32, i32* [[TMP10]], i32 0 573; CHECK-NEXT: [[TMP12:%.*]] = bitcast i32* [[TMP11]] to <vscale x 4 x i32>* 574; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <vscale x 4 x i32> @llvm.masked.load.nxv4i32.p0nxv4i32(<vscale x 4 x i32>* [[TMP12]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x i32> poison) 575; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> [[WIDE_MASKED_LOAD]], <vscale x 4 x i32*> [[BROADCAST_SPLAT]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 576; CHECK-NEXT: [[TMP13:%.*]] = call i64 @llvm.vscale.i64() 577; CHECK-NEXT: [[TMP14:%.*]] = mul i64 [[TMP13]], 4 578; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP14]] 579; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT]], i64 [[N]]) 580; CHECK-NEXT: [[TMP15:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 581; CHECK-NEXT: [[TMP16:%.*]] = extractelement <vscale x 4 x i1> [[TMP15]], i32 0 582; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] 583; CHECK: middle.block: 584; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] 585; CHECK: scalar.ph: 586; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 587; CHECK-NEXT: br label [[FOR_BODY:%.*]] 588; CHECK: for.body: 589; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 590; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[INDVARS_IV]] 591; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 592; CHECK-NEXT: store i32 [[VAL]], i32* [[DST]], align 4 593; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 594; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[N]] 595; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP17:![0-9]+]] 596; CHECK: for.end: 597; CHECK-NEXT: ret void 598; 599 600entry: 601 br label %for.body 602 603for.body: ; preds = %entry, %for.body 604 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 605 %arrayidx = getelementptr inbounds i32, i32* %src, i64 %indvars.iv 606 %val = load i32, i32* %arrayidx, align 4 607 store i32 %val, i32* %dst, align 4 608 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 609 %exitcond.not = icmp eq i64 %indvars.iv.next, %n 610 br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 611 612for.end: ; preds = %for.body, %entry 613 ret void 614} 615 616 617define void @simple_fdiv(float* noalias %dst, float* noalias %src, i64 %n) #0 { 618; CHECK-LABEL: @simple_fdiv( 619; CHECK-NEXT: entry: 620; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 1) 621; CHECK-NEXT: [[TMP0:%.*]] = sub i64 -1, [[UMAX]] 622; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 623; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 624; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]] 625; CHECK-NEXT: br i1 [[TMP3]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 626; CHECK: vector.ph: 627; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() 628; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 4 629; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 630; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 631; CHECK-NEXT: [[TMP8:%.*]] = sub i64 [[TMP7]], 1 632; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[UMAX]], [[TMP8]] 633; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP5]] 634; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 635; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[UMAX]]) 636; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 637; CHECK: vector.body: 638; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT3:%.*]], [[VECTOR_BODY]] ] 639; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 4 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] 640; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX1]], 0 641; CHECK-NEXT: [[TMP10:%.*]] = getelementptr float, float* [[SRC:%.*]], i64 [[TMP9]] 642; CHECK-NEXT: [[TMP11:%.*]] = getelementptr float, float* [[DST:%.*]], i64 [[TMP9]] 643; CHECK-NEXT: [[TMP12:%.*]] = getelementptr float, float* [[TMP10]], i32 0 644; CHECK-NEXT: [[TMP13:%.*]] = bitcast float* [[TMP12]] to <vscale x 4 x float>* 645; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0nxv4f32(<vscale x 4 x float>* [[TMP13]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x float> poison) 646; CHECK-NEXT: [[TMP14:%.*]] = getelementptr float, float* [[TMP11]], i32 0 647; CHECK-NEXT: [[TMP15:%.*]] = bitcast float* [[TMP14]] to <vscale x 4 x float>* 648; CHECK-NEXT: [[WIDE_MASKED_LOAD2:%.*]] = call <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0nxv4f32(<vscale x 4 x float>* [[TMP15]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]], <vscale x 4 x float> poison) 649; CHECK-NEXT: [[TMP16:%.*]] = fdiv <vscale x 4 x float> [[WIDE_MASKED_LOAD]], [[WIDE_MASKED_LOAD2]] 650; CHECK-NEXT: [[TMP17:%.*]] = bitcast float* [[TMP14]] to <vscale x 4 x float>* 651; CHECK-NEXT: call void @llvm.masked.store.nxv4f32.p0nxv4f32(<vscale x 4 x float> [[TMP16]], <vscale x 4 x float>* [[TMP17]], i32 4, <vscale x 4 x i1> [[ACTIVE_LANE_MASK]]) 652; CHECK-NEXT: [[TMP18:%.*]] = call i64 @llvm.vscale.i64() 653; CHECK-NEXT: [[TMP19:%.*]] = mul i64 [[TMP18]], 4 654; CHECK-NEXT: [[INDEX_NEXT3]] = add i64 [[INDEX1]], [[TMP19]] 655; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX_NEXT3]], i64 [[UMAX]]) 656; CHECK-NEXT: [[TMP20:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i32 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) 657; CHECK-NEXT: [[TMP21:%.*]] = extractelement <vscale x 4 x i1> [[TMP20]], i32 0 658; CHECK-NEXT: br i1 [[TMP21]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]] 659; CHECK: middle.block: 660; CHECK-NEXT: br i1 true, label [[WHILE_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] 661; CHECK: scalar.ph: 662; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 663; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 664; CHECK: while.body: 665; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 666; CHECK-NEXT: [[GEP1:%.*]] = getelementptr float, float* [[SRC]], i64 [[INDEX]] 667; CHECK-NEXT: [[GEP2:%.*]] = getelementptr float, float* [[DST]], i64 [[INDEX]] 668; CHECK-NEXT: [[VAL1:%.*]] = load float, float* [[GEP1]], align 4 669; CHECK-NEXT: [[VAL2:%.*]] = load float, float* [[GEP2]], align 4 670; CHECK-NEXT: [[RES:%.*]] = fdiv float [[VAL1]], [[VAL2]] 671; CHECK-NEXT: store float [[RES]], float* [[GEP2]], align 4 672; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 1 673; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N]] 674; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT]], !llvm.loop [[LOOP19:![0-9]+]] 675; CHECK: while.end.loopexit: 676; CHECK-NEXT: ret void 677; 678entry: 679 br label %while.body 680 681while.body: ; preds = %while.body, %entry 682 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 683 %gep1 = getelementptr float, float* %src, i64 %index 684 %gep2 = getelementptr float, float* %dst, i64 %index 685 %val1 = load float, float* %gep1 686 %val2 = load float, float* %gep2 687 %res = fdiv float %val1, %val2 688 store float %res, float* %gep2 689 %index.next = add nsw i64 %index, 1 690 %cmp10 = icmp ult i64 %index.next, %n 691 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !0 692 693while.end.loopexit: ; preds = %while.body 694 ret void 695} 696 697; Negative tests where we don't expect tail-folding 698 699; Integer divides can throw exceptions and since we can't scalarize conditional 700; divides for scalable vectors we just don't bother vectorizing. 701define void @simple_idiv(i32* noalias %dst, i32* noalias %src, i64 %n) #0 { 702; CHECK-LABEL: @simple_idiv( 703; CHECK-NEXT: entry: 704; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 705; CHECK: while.body: 706; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[WHILE_BODY]] ], [ 0, [[ENTRY:%.*]] ] 707; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, i32* [[SRC:%.*]], i64 [[INDEX]] 708; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[INDEX]] 709; CHECK-NEXT: [[VAL1:%.*]] = load i32, i32* [[GEP1]], align 4 710; CHECK-NEXT: [[VAL2:%.*]] = load i32, i32* [[GEP2]], align 4 711; CHECK-NEXT: [[RES:%.*]] = udiv i32 [[VAL1]], [[VAL2]] 712; CHECK-NEXT: store i32 [[RES]], i32* [[GEP2]], align 4 713; CHECK-NEXT: [[INDEX_NEXT]] = add nsw i64 [[INDEX]], 1 714; CHECK-NEXT: [[CMP10:%.*]] = icmp ult i64 [[INDEX_NEXT]], [[N:%.*]] 715; CHECK-NEXT: br i1 [[CMP10]], label [[WHILE_BODY]], label [[WHILE_END_LOOPEXIT:%.*]], !llvm.loop [[LOOP20:![0-9]+]] 716; CHECK: while.end.loopexit: 717; CHECK-NEXT: ret void 718; 719entry: 720 br label %while.body 721 722while.body: ; preds = %while.body, %entry 723 %index = phi i64 [ %index.next, %while.body ], [ 0, %entry ] 724 %gep1 = getelementptr i32, i32* %src, i64 %index 725 %gep2 = getelementptr i32, i32* %dst, i64 %index 726 %val1 = load i32, i32* %gep1 727 %val2 = load i32, i32* %gep2 728 %res = udiv i32 %val1, %val2 729 store i32 %res, i32* %gep2 730 %index.next = add nsw i64 %index, 1 731 %cmp10 = icmp ult i64 %index.next, %n 732 br i1 %cmp10, label %while.body, label %while.end.loopexit, !llvm.loop !0 733 734while.end.loopexit: ; preds = %while.body 735 ret void 736} 737 738!0 = distinct !{!0, !1, !2} 739!1 = !{!"llvm.loop.vectorize.width", i32 4} 740!2 = !{!"llvm.loop.vectorize.scalable.enable", i1 true} 741!3 = distinct !{!3, !4} 742!4 = !{!"llvm.loop.vectorize.width", i32 4} 743 744attributes #0 = { "target-features"="+sve" } 745