845 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "^middle.block" --version 52; RUN: opt %s -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S | FileCheck %s3 4; Make sure that integer poison-generating flags (i.e., nuw/nsw, exact and inbounds)5; are dropped from instructions in blocks that need predication and are linearized6; and masked after vectorization. We only drop flags from scalar instructions that7; contribute to the address computation of a masked vector load/store. After8; linearizing the control flow and removing their guarding condition, these9; instructions could generate a poison value which would be used as base address of10; the masked vector load/store (see PR52111). For gather/scatter cases,11; posiong-generating flags can be preserved since poison addresses in the vector GEP12; reaching the gather/scatter instruction will be masked-out by the gather/scatter13; instruction itself and won't be used.14; We need AVX512 target features for the loop to be vectorized with masks instead of15; predicates.16 17target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"18target triple = "x86_64-pc-linux-gnu"19 20; Drop poison-generating flags from 'sub' and 'getelementptr' feeding a masked load.21; Test for PR52111.22define void @drop_scalar_nuw_nsw(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {23; CHECK-LABEL: define void @drop_scalar_nuw_nsw(24; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {25; CHECK-NEXT: [[ENTRY:.*:]]26; CHECK-NEXT: br label %[[VECTOR_PH:.*]]27; CHECK: [[VECTOR_PH]]:28; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]29; CHECK: [[VECTOR_BODY]]:30; CHECK-NEXT: [[TMP0:%.*]] = getelementptr float, ptr [[INPUT]], i64 -131; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[TMP0]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0:![0-9]+]]32; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_LOAD]], <4 x float> zeroinitializer33; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 434; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]35; CHECK: [[MIDDLE_BLOCK]]:36;37entry:38 br label %loop.header39 40loop.header:41 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]42 %i23 = icmp eq i64 %iv, 043 br i1 %i23, label %if.end, label %if.then44 45if.then:46 %i27 = sub nuw nsw i64 %iv, 147 %i29 = getelementptr inbounds float, ptr %input, i64 %i2748 %i30 = load float, ptr %i29, align 4, !invariant.load !049 br label %if.end50 51if.end:52 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]53 %i35 = getelementptr inbounds float, ptr %output, i64 %iv54 store float %i34, ptr %i35, align 455 %iv.inc = add nuw nsw i64 %iv, 156 %exitcond = icmp eq i64 %iv.inc, 457 br i1 %exitcond, label %loop.exit, label %loop.header58 59loop.exit:60 ret void61}62 63; Variant with getelementptr nusw.64define void @drop_scalar_gep_nusw(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {65; CHECK-LABEL: define void @drop_scalar_gep_nusw(66; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {67; CHECK-NEXT: [[ENTRY:.*:]]68; CHECK-NEXT: br label %[[VECTOR_PH:.*]]69; CHECK: [[VECTOR_PH]]:70; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]71; CHECK: [[VECTOR_BODY]]:72; CHECK-NEXT: [[TMP0:%.*]] = getelementptr float, ptr [[INPUT]], i64 -173; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[TMP0]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0]]74; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_LOAD]], <4 x float> zeroinitializer75; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 476; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]77; CHECK: [[MIDDLE_BLOCK]]:78;79entry:80 br label %loop.header81 82loop.header:83 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]84 %i23 = icmp eq i64 %iv, 085 br i1 %i23, label %if.end, label %if.then86 87if.then:88 %i27 = sub nuw nsw i64 %iv, 189 %i29 = getelementptr nusw float, ptr %input, i64 %i2790 %i30 = load float, ptr %i29, align 4, !invariant.load !091 br label %if.end92 93if.end:94 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]95 %i35 = getelementptr nusw float, ptr %output, i64 %iv96 store float %i34, ptr %i35, align 497 %iv.inc = add nuw nsw i64 %iv, 198 %exitcond = icmp eq i64 %iv.inc, 499 br i1 %exitcond, label %loop.exit, label %loop.header100 101loop.exit:102 ret void103}104 105; Variant with getelementptr nuw.106define void @drop_scalar_gep_nuw(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {107; CHECK-LABEL: define void @drop_scalar_gep_nuw(108; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {109; CHECK-NEXT: [[ENTRY:.*:]]110; CHECK-NEXT: br label %[[VECTOR_PH:.*]]111; CHECK: [[VECTOR_PH]]:112; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]113; CHECK: [[VECTOR_BODY]]:114; CHECK-NEXT: [[TMP0:%.*]] = getelementptr float, ptr [[INPUT]], i64 -1115; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[TMP0]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0]]116; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_LOAD]], <4 x float> zeroinitializer117; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 4118; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]119; CHECK: [[MIDDLE_BLOCK]]:120;121entry:122 br label %loop.header123 124loop.header:125 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]126 %i23 = icmp eq i64 %iv, 0127 br i1 %i23, label %if.end, label %if.then128 129if.then:130 %i27 = sub nuw nsw i64 %iv, 1131 %i29 = getelementptr nuw float, ptr %input, i64 %i27132 %i30 = load float, ptr %i29, align 4, !invariant.load !0133 br label %if.end134 135if.end:136 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]137 %i35 = getelementptr nuw float, ptr %output, i64 %iv138 store float %i34, ptr %i35, align 4139 %iv.inc = add nuw nsw i64 %iv, 1140 %exitcond = icmp eq i64 %iv.inc, 4141 br i1 %exitcond, label %loop.exit, label %loop.header142 143loop.exit:144 ret void145}146 147; Drop poison-generating flags from 'sub' and 'getelementptr' feeding a masked load.148; In this case, 'sub' and 'getelementptr' are not guarded by the predicate.149define void @drop_nonpred_scalar_nuw_nsw(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {150; CHECK-LABEL: define void @drop_nonpred_scalar_nuw_nsw(151; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {152; CHECK-NEXT: [[ENTRY:.*:]]153; CHECK-NEXT: br label %[[VECTOR_PH:.*]]154; CHECK: [[VECTOR_PH]]:155; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]156; CHECK: [[VECTOR_BODY]]:157; CHECK-NEXT: [[TMP0:%.*]] = getelementptr float, ptr [[INPUT]], i64 -1158; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[TMP0]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0]]159; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_LOAD]], <4 x float> zeroinitializer160; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 4161; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]162; CHECK: [[MIDDLE_BLOCK]]:163;164entry:165 br label %loop.header166 167loop.header:168 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]169 %i27 = sub i64 %iv, 1170 %i29 = getelementptr float, ptr %input, i64 %i27171 %i23 = icmp eq i64 %iv, 0172 br i1 %i23, label %if.end, label %if.then173 174if.then:175 %i30 = load float, ptr %i29, align 4, !invariant.load !0176 br label %if.end177 178if.end:179 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]180 %i35 = getelementptr inbounds float, ptr %output, i64 %iv181 store float %i34, ptr %i35, align 4182 %iv.inc = add nuw nsw i64 %iv, 1183 %exitcond = icmp eq i64 %iv.inc, 4184 br i1 %exitcond, label %loop.exit, label %loop.header185 186loop.exit:187 ret void188}189 190; Preserve poison-generating flags from vector 'sub', 'mul' and 'getelementptr' feeding a masked gather.191define void @preserve_vector_nuw_nsw(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {192; CHECK-LABEL: define void @preserve_vector_nuw_nsw(193; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {194; CHECK-NEXT: [[ENTRY:.*:]]195; CHECK-NEXT: br label %[[VECTOR_PH:.*]]196; CHECK: [[VECTOR_PH]]:197; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]198; CHECK: [[VECTOR_BODY]]:199; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds float, ptr [[INPUT]], <4 x i64> <i64 -2, i64 0, i64 2, i64 4>200; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x float> @llvm.masked.gather.v4f32.v4p0(<4 x ptr> align 4 [[TMP0]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0]]201; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_GATHER]], <4 x float> zeroinitializer202; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 4203; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]204; CHECK: [[MIDDLE_BLOCK]]:205;206entry:207 br label %loop.header208 209loop.header:210 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]211 %i23 = icmp eq i64 %iv, 0212 br i1 %i23, label %if.end, label %if.then213 214if.then:215 %i27 = sub nuw nsw i64 %iv, 1216 %i28 = mul nuw nsw i64 %i27, 2217 %i29 = getelementptr inbounds float, ptr %input, i64 %i28218 %i30 = load float, ptr %i29, align 4, !invariant.load !0219 br label %if.end220 221if.end:222 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]223 %i35 = getelementptr inbounds float, ptr %output, i64 %iv224 store float %i34, ptr %i35, align 4225 %iv.inc = add nuw nsw i64 %iv, 1226 %exitcond = icmp eq i64 %iv.inc, 4227 br i1 %exitcond, label %loop.exit, label %loop.header228 229loop.exit:230 ret void231}232 233; Drop poison-generating flags from vector 'sub' and 'gep' feeding a masked load.234define void @drop_vector_nuw_nsw(ptr noalias nocapture readonly %input, ptr %output, ptr noalias %ptrs) local_unnamed_addr #0 {235; CHECK-LABEL: define void @drop_vector_nuw_nsw(236; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]], ptr noalias [[PTRS:%.*]]) local_unnamed_addr #[[ATTR0]] {237; CHECK-NEXT: [[ENTRY:.*:]]238; CHECK-NEXT: br label %[[VECTOR_PH:.*]]239; CHECK: [[VECTOR_PH]]:240; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]241; CHECK: [[VECTOR_BODY]]:242; CHECK-NEXT: [[TMP3:%.*]] = getelementptr float, ptr [[INPUT]], <4 x i64> <i64 -1, i64 0, i64 1, i64 2>243; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x ptr> [[TMP3]], i32 0244; CHECK-NEXT: store <4 x ptr> [[TMP3]], ptr [[PTRS]], align 8245; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[TMP6]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0]]246; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_LOAD]], <4 x float> zeroinitializer247; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 4248; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]249; CHECK: [[MIDDLE_BLOCK]]:250;251entry:252 br label %loop.header253 254loop.header:255 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]256 %i23 = icmp eq i64 %iv, 0257 %gep = getelementptr inbounds ptr, ptr %ptrs, i64 %iv258 %i27 = sub nuw nsw i64 %iv, 1259 %i29 = getelementptr inbounds float, ptr %input, i64 %i27260 store ptr %i29, ptr %gep261 br i1 %i23, label %if.end, label %if.then262 263if.then:264 %i30 = load float, ptr %i29, align 4, !invariant.load !0265 br label %if.end266 267if.end:268 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]269 %i35 = getelementptr inbounds float, ptr %output, i64 %iv270 store float %i34, ptr %i35, align 4271 %iv.inc = add nuw nsw i64 %iv, 1272 %exitcond = icmp eq i64 %iv.inc, 4273 br i1 %exitcond, label %loop.exit, label %loop.header274 275loop.exit:276 ret void277}278 279; Same as @drop_vector_nuw_nsw, except built with avx1; in this case,280; we make scalar clones of the 'sub' operation. These clones also need281; cleared flags.282define void @drop_nonvector_nuw_nsw_avx1(ptr noalias nocapture readonly %input, ptr %output, ptr noalias %ptrs) local_unnamed_addr #1 {283; CHECK-LABEL: define void @drop_nonvector_nuw_nsw_avx1(284; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]], ptr noalias [[PTRS:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {285; CHECK-NEXT: [[ENTRY:.*:]]286; CHECK-NEXT: br label %[[VECTOR_PH:.*]]287; CHECK: [[VECTOR_PH]]:288; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]289; CHECK: [[VECTOR_BODY]]:290; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds ptr, ptr [[PTRS]], i64 0291; CHECK-NEXT: [[TMP6:%.*]] = sub i64 0, 1292; CHECK-NEXT: [[TMP7:%.*]] = sub i64 1, 1293; CHECK-NEXT: [[TMP8:%.*]] = sub i64 2, 1294; CHECK-NEXT: [[TMP9:%.*]] = sub i64 3, 1295; CHECK-NEXT: [[TMP10:%.*]] = getelementptr float, ptr [[INPUT]], i64 [[TMP6]]296; CHECK-NEXT: [[TMP11:%.*]] = getelementptr float, ptr [[INPUT]], i64 [[TMP7]]297; CHECK-NEXT: [[TMP12:%.*]] = getelementptr float, ptr [[INPUT]], i64 [[TMP8]]298; CHECK-NEXT: [[TMP13:%.*]] = getelementptr float, ptr [[INPUT]], i64 [[TMP9]]299; CHECK-NEXT: [[TMP14:%.*]] = insertelement <4 x ptr> poison, ptr [[TMP10]], i32 0300; CHECK-NEXT: [[TMP15:%.*]] = insertelement <4 x ptr> [[TMP14]], ptr [[TMP11]], i32 1301; CHECK-NEXT: [[TMP16:%.*]] = insertelement <4 x ptr> [[TMP15]], ptr [[TMP12]], i32 2302; CHECK-NEXT: [[TMP17:%.*]] = insertelement <4 x ptr> [[TMP16]], ptr [[TMP13]], i32 3303; CHECK-NEXT: store <4 x ptr> [[TMP17]], ptr [[TMP5]], align 8304; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[TMP10]], <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> poison), !invariant.load [[META0]]305; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x float> [[WIDE_MASKED_LOAD]], <4 x float> zeroinitializer306; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds float, ptr [[OUTPUT]], i64 0307; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[TMP21]], align 4308; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]309; CHECK: [[MIDDLE_BLOCK]]:310;311entry:312 br label %loop.header313 314loop.header:315 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]316 %i23 = icmp eq i64 %iv, 0317 %gep = getelementptr inbounds ptr, ptr %ptrs, i64 %iv318 %i27 = sub nuw nsw i64 %iv, 1319 %i29 = getelementptr inbounds float, ptr %input, i64 %i27320 store ptr %i29, ptr %gep321 br i1 %i23, label %if.end, label %if.then322 323if.then:324 %i30 = load float, ptr %i29, align 4, !invariant.load !0325 br label %if.end326 327if.end:328 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]329 %i35 = getelementptr inbounds float, ptr %output, i64 %iv330 store float %i34, ptr %i35, align 4331 %iv.inc = add nuw nsw i64 %iv, 1332 %exitcond = icmp eq i64 %iv.inc, 4333 br i1 %exitcond, label %loop.exit, label %loop.header334 335loop.exit:336 ret void337}338 339; Preserve poison-generating flags from 'sub', which is not contributing to any address computation340; of any masked load/store/gather/scatter.341define void @preserve_nuw_nsw_no_addr(ptr %output) local_unnamed_addr #0 {342; CHECK-LABEL: define void @preserve_nuw_nsw_no_addr(343; CHECK-SAME: ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {344; CHECK-NEXT: [[ENTRY:.*:]]345; CHECK-NEXT: br label %[[VECTOR_PH:.*]]346; CHECK: [[VECTOR_PH]]:347; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]348; CHECK: [[VECTOR_BODY]]:349; CHECK-NEXT: store <4 x i64> <i64 0, i64 0, i64 1, i64 2>, ptr [[OUTPUT]], align 4350; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]351; CHECK: [[MIDDLE_BLOCK]]:352;353entry:354 br label %loop.header355 356loop.header:357 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]358 %i23 = icmp eq i64 %iv, 0359 br i1 %i23, label %if.end, label %if.then360 361if.then:362 %i27 = sub nuw nsw i64 %iv, 1363 br label %if.end364 365if.end:366 %i34 = phi i64 [ 0, %loop.header ], [ %i27, %if.then ]367 %i35 = getelementptr inbounds i64, ptr %output, i64 %iv368 store i64 %i34, ptr %i35, align 4369 %iv.inc = add nuw nsw i64 %iv, 1370 %exitcond = icmp eq i64 %iv.inc, 4371 br i1 %exitcond, label %loop.exit, label %loop.header372 373loop.exit:374 ret void375}376 377; Drop poison-generating flags from 'sdiv' and 'getelementptr' feeding a masked load.378define void @drop_scalar_exact(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {379; CHECK-LABEL: define void @drop_scalar_exact(380; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {381; CHECK-NEXT: [[ENTRY:.*:]]382; CHECK-NEXT: br label %[[VECTOR_PH:.*]]383; CHECK: [[VECTOR_PH]]:384; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]385; CHECK: [[VECTOR_BODY]]:386; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x float> @llvm.masked.load.v4f32.p0(ptr align 4 [[INPUT]], <4 x i1> <i1 true, i1 true, i1 false, i1 true>, <4 x float> poison), !invariant.load [[META0]]387; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 false, i1 true, i1 false>, <4 x float> zeroinitializer, <4 x float> [[WIDE_MASKED_LOAD]]388; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 4389; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]390; CHECK: [[MIDDLE_BLOCK]]:391;392entry:393 br label %loop.header394 395loop.header:396 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]397 %i7 = icmp ne i64 %iv, 0398 %i8 = and i64 %iv, 1399 %i9 = icmp eq i64 %i8, 0400 %i10 = and i1 %i7, %i9401 br i1 %i10, label %if.end, label %if.then402 403if.then:404 %i26 = sdiv exact i64 %iv, 1405 %i29 = getelementptr inbounds float, ptr %input, i64 %i26406 %i30 = load float, ptr %i29, align 4, !invariant.load !0407 br label %if.end408 409if.end:410 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]411 %i35 = getelementptr inbounds float, ptr %output, i64 %iv412 store float %i34, ptr %i35, align 4413 %iv.inc = add nuw nsw i64 %iv, 1414 %exitcond = icmp eq i64 %iv.inc, 4415 br i1 %exitcond, label %loop.exit, label %loop.header416 417loop.exit:418 ret void419}420 421define void @drop_zext_nneg(ptr noalias %p, ptr noalias %p1) #0 {422; CHECK-LABEL: define void @drop_zext_nneg(423; CHECK-SAME: ptr noalias [[P:%.*]], ptr noalias [[P1:%.*]]) #[[ATTR0]] {424; CHECK-NEXT: [[ENTRY:.*:]]425; CHECK-NEXT: br label %[[VECTOR_PH:.*]]426; CHECK: [[VECTOR_PH]]:427; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]428; CHECK: [[VECTOR_BODY]]:429; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]430; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i32> [ <i32 0, i32 1, i32 2, i32 3>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]431; CHECK-NEXT: [[TMP0:%.*]] = icmp eq <4 x i32> [[VEC_IND]], zeroinitializer432; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i32> [[VEC_IND]] to <4 x i64>433; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i64> [[TMP1]], i32 0434; CHECK-NEXT: [[TMP3:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP2]]435; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x double> @llvm.masked.load.v4f64.p0(ptr align 8 [[TMP3]], <4 x i1> [[TMP0]], <4 x double> poison)436; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP0]], <4 x double> [[WIDE_MASKED_LOAD]], <4 x double> zeroinitializer437; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[PREDPHI]], i32 3438; CHECK-NEXT: store double [[TMP5]], ptr [[P1]], align 8439; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4440; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i32> [[VEC_IND]], splat (i32 4)441; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024442; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP1:![0-9]+]]443; CHECK: [[MIDDLE_BLOCK]]:444;445entry:446 br label %body447 448body:449 %iv = phi i64 [ %next, %else ], [ 0, %entry ]450 %0 = trunc i64 %iv to i32451 %c = icmp eq i32 %0, 0452 br i1 %c, label %then, label %else453 454then:455 %zext = zext nneg i32 %0 to i64456 %idx1 = getelementptr double, ptr %p, i64 %zext457 %idx2 = getelementptr double, ptr %p, i64 %zext458 %1 = load double, ptr %idx2, align 8459 br label %else460 461else:462 %phi = phi double [ %1, %then ], [ 0.000000e+00, %body ]463 store double %phi, ptr %p1, align 8464 %next = add i64 %iv, 1465 %cmp = icmp eq i64 %next, 1024466 br i1 %cmp, label %exit, label %body467 468exit:469 ret void470}471 472; Preserve poison-generating flags from 'sdiv' and 'getelementptr' feeding a masked gather.473define void @preserve_vector_exact_no_addr(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {474; CHECK-LABEL: define void @preserve_vector_exact_no_addr(475; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {476; CHECK-NEXT: [[ENTRY:.*:]]477; CHECK-NEXT: br label %[[VECTOR_PH:.*]]478; CHECK: [[VECTOR_PH]]:479; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]480; CHECK: [[VECTOR_BODY]]:481; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds float, ptr [[INPUT]], <4 x i64> <i64 0, i64 0, i64 1, i64 1>482; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x float> @llvm.masked.gather.v4f32.v4p0(<4 x ptr> align 4 [[TMP0]], <4 x i1> <i1 true, i1 true, i1 false, i1 true>, <4 x float> poison), !invariant.load [[META0]]483; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> <i1 false, i1 false, i1 true, i1 false>, <4 x float> zeroinitializer, <4 x float> [[WIDE_MASKED_GATHER]]484; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[OUTPUT]], align 4485; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]486; CHECK: [[MIDDLE_BLOCK]]:487;488entry:489 br label %loop.header490 491loop.header:492 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]493 %i7 = icmp ne i64 %iv, 0494 %i8 = and i64 %iv, 1495 %i9 = icmp eq i64 %i8, 0496 %i10 = and i1 %i7, %i9497 br i1 %i10, label %if.end, label %if.then498 499if.then:500 %i26 = sdiv exact i64 %iv, 2501 %i29 = getelementptr inbounds float, ptr %input, i64 %i26502 %i30 = load float, ptr %i29, align 4, !invariant.load !0503 br label %if.end504 505if.end:506 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]507 %i35 = getelementptr inbounds float, ptr %output, i64 %iv508 store float %i34, ptr %i35, align 4509 %iv.inc = add nuw nsw i64 %iv, 1510 %exitcond = icmp eq i64 %iv.inc, 4511 br i1 %exitcond, label %loop.exit, label %loop.header512 513loop.exit:514 ret void515}516 517; Preserve poison-generating flags from 'sdiv', which is not contributing to any address computation518; of any masked load/store/gather/scatter.519define void @preserve_exact_no_addr(ptr %output) local_unnamed_addr #0 {520; CHECK-LABEL: define void @preserve_exact_no_addr(521; CHECK-SAME: ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {522; CHECK-NEXT: [[ENTRY:.*:]]523; CHECK-NEXT: br label %[[VECTOR_PH:.*]]524; CHECK: [[VECTOR_PH]]:525; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]526; CHECK: [[VECTOR_BODY]]:527; CHECK-NEXT: store <4 x i64> <i64 0, i64 0, i64 1, i64 1>, ptr [[OUTPUT]], align 4528; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]529; CHECK: [[MIDDLE_BLOCK]]:530;531entry:532 br label %loop.header533 534loop.header:535 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]536 %i23 = icmp eq i64 %iv, 0537 br i1 %i23, label %if.end, label %if.then538 539if.then:540 %i27 = sdiv exact i64 %iv, 2541 br label %if.end542 543if.end:544 %i34 = phi i64 [ 0, %loop.header ], [ %i27, %if.then ]545 %i35 = getelementptr inbounds i64, ptr %output, i64 %iv546 store i64 %i34, ptr %i35, align 4547 %iv.inc = add nuw nsw i64 %iv, 1548 %exitcond = icmp eq i64 %iv.inc, 4549 br i1 %exitcond, label %loop.exit, label %loop.header550 551loop.exit:552 ret void553}554 555; Make sure we don't vectorize a loop with a phi feeding a poison value to556; a masked load/gather.557define void @dont_vectorize_poison_phi(ptr noalias nocapture readonly %input, ptr %output) local_unnamed_addr #0 {558; CHECK-LABEL: define void @dont_vectorize_poison_phi(559; CHECK-SAME: ptr noalias readonly captures(none) [[INPUT:%.*]], ptr [[OUTPUT:%.*]]) local_unnamed_addr #[[ATTR0]] {560; CHECK-NEXT: [[ENTRY:.*]]:561; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]562; CHECK: [[LOOP_HEADER]]:563; CHECK-NEXT: [[POISON:%.*]] = phi i64 [ poison, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[IF_END:.*]] ]564; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_INC]], %[[IF_END]] ]565; CHECK-NEXT: [[I23:%.*]] = icmp eq i64 [[IV]], 0566; CHECK-NEXT: br i1 [[I23]], label %[[IF_END]], label %[[IF_THEN:.*]]567; CHECK: [[IF_THEN]]:568; CHECK-NEXT: [[I29:%.*]] = getelementptr inbounds float, ptr [[INPUT]], i64 [[POISON]]569; CHECK-NEXT: [[I30:%.*]] = load float, ptr [[I29]], align 4, !invariant.load [[META0]]570; CHECK-NEXT: br label %[[IF_END]]571; CHECK: [[IF_END]]:572; CHECK-NEXT: [[I34:%.*]] = phi float [ 0.000000e+00, %[[LOOP_HEADER]] ], [ [[I30]], %[[IF_THEN]] ]573; CHECK-NEXT: [[I35:%.*]] = getelementptr inbounds float, ptr [[OUTPUT]], i64 [[IV]]574; CHECK-NEXT: store float [[I34]], ptr [[I35]], align 4575; CHECK-NEXT: [[IV_INC]] = add nuw nsw i64 [[IV]], 1576; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_INC]], 4577; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP_EXIT:.*]], label %[[LOOP_HEADER]]578; CHECK: [[LOOP_EXIT]]:579; CHECK-NEXT: ret void580;581entry:582 br label %loop.header583 584loop.header:585 %poison = phi i64 [ poison, %entry ], [ %iv.inc, %if.end ]586 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %if.end ]587 %i23 = icmp eq i64 %iv, 0588 br i1 %i23, label %if.end, label %if.then589 590if.then:591 %i29 = getelementptr inbounds float, ptr %input, i64 %poison592 %i30 = load float, ptr %i29, align 4, !invariant.load !0593 br label %if.end594 595if.end:596 %i34 = phi float [ 0.000000e+00, %loop.header ], [ %i30, %if.then ]597 %i35 = getelementptr inbounds float, ptr %output, i64 %iv598 store float %i34, ptr %i35, align 4599 %iv.inc = add nuw nsw i64 %iv, 1600 %exitcond = icmp eq i64 %iv.inc, 4601 br i1 %exitcond, label %loop.exit, label %loop.header602 603loop.exit:604 ret void605}606 607@c = external global [5 x i8]608 609; Test case for https://github.com/llvm/llvm-project/issues/70590.610; Note that the then block has UB, but I could not find any other way to611; construct a suitable test case.612define void @pr70590_recipe_without_underlying_instr(i64 %n, ptr noalias %dst) {613; CHECK-LABEL: define void @pr70590_recipe_without_underlying_instr(614; CHECK-SAME: i64 [[N:%.*]], ptr noalias [[DST:%.*]]) {615; CHECK-NEXT: [[ENTRY:.*:]]616; CHECK-NEXT: br label %[[VECTOR_PH:.*]]617; CHECK: [[VECTOR_PH]]:618; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i64> poison, i64 [[N]], i64 0619; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> poison, <4 x i32> zeroinitializer620; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]621; CHECK: [[VECTOR_BODY]]:622; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i64> <i64 0, i64 1, i64 2, i64 3>, [[BROADCAST_SPLAT]]623; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0624; CHECK-NEXT: br i1 [[TMP2]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]625; CHECK: [[PRED_LOAD_IF]]:626; CHECK-NEXT: [[TMP4:%.*]] = add i64 0, poison627; CHECK-NEXT: [[TMP23:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP4]]628; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP23]], align 1629; CHECK-NEXT: [[TMP24:%.*]] = insertelement <4 x i8> poison, i8 [[TMP6]], i32 0630; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]631; CHECK: [[PRED_LOAD_CONTINUE]]:632; CHECK-NEXT: [[TMP8:%.*]] = phi <4 x i8> [ poison, %[[VECTOR_BODY]] ], [ [[TMP24]], %[[PRED_LOAD_IF]] ]633; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1634; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2:.*]]635; CHECK: [[PRED_LOAD_IF1]]:636; CHECK-NEXT: [[TMP11:%.*]] = add i64 1, poison637; CHECK-NEXT: [[TMP25:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP11]]638; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP25]], align 1639; CHECK-NEXT: [[TMP14:%.*]] = insertelement <4 x i8> [[TMP8]], i8 [[TMP26]], i32 1640; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]641; CHECK: [[PRED_LOAD_CONTINUE2]]:642; CHECK-NEXT: [[TMP29:%.*]] = phi <4 x i8> [ [[TMP8]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]643; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2644; CHECK-NEXT: br i1 [[TMP7]], label %[[PRED_LOAD_IF3:.*]], label %[[PRED_LOAD_CONTINUE4:.*]]645; CHECK: [[PRED_LOAD_IF3]]:646; CHECK-NEXT: [[TMP18:%.*]] = add i64 2, poison647; CHECK-NEXT: [[TMP19:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP18]]648; CHECK-NEXT: [[TMP20:%.*]] = load i8, ptr [[TMP19]], align 1649; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP29]], i8 [[TMP20]], i32 2650; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE4]]651; CHECK: [[PRED_LOAD_CONTINUE4]]:652; CHECK-NEXT: [[TMP22:%.*]] = phi <4 x i8> [ [[TMP29]], %[[PRED_LOAD_CONTINUE2]] ], [ [[TMP21]], %[[PRED_LOAD_IF3]] ]653; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3654; CHECK-NEXT: br i1 [[TMP9]], label %[[PRED_LOAD_IF5:.*]], label %[[PRED_LOAD_CONTINUE6:.*]]655; CHECK: [[PRED_LOAD_IF5]]:656; CHECK-NEXT: [[TMP12:%.*]] = add i64 3, poison657; CHECK-NEXT: [[TMP13:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP12]]658; CHECK-NEXT: [[TMP27:%.*]] = load i8, ptr [[TMP13]], align 1659; CHECK-NEXT: [[TMP28:%.*]] = insertelement <4 x i8> [[TMP22]], i8 [[TMP27]], i32 3660; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE6]]661; CHECK: [[PRED_LOAD_CONTINUE6]]:662; CHECK-NEXT: [[TMP30:%.*]] = phi <4 x i8> [ [[TMP22]], %[[PRED_LOAD_CONTINUE4]] ], [ [[TMP28]], %[[PRED_LOAD_IF5]] ]663; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> [[TMP30]], <4 x i8> zeroinitializer664; CHECK-NEXT: store <4 x i8> [[PREDPHI]], ptr [[DST]], align 4665; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]666; CHECK: [[MIDDLE_BLOCK]]:667;668 669entry:670 br label %loop.header671 672loop.header:673 %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ]674 %cmp = icmp eq i64 %iv, %n675 br i1 %cmp, label %loop.latch, label %then676 677then:678 %rem = srem i64 3, 0679 %add3 = add i64 %rem, -3680 %add5 = add i64 %iv, %add3681 %gep = getelementptr [5 x i8], ptr @c, i64 0, i64 %add5682 %l = load i8, ptr %gep, align 1683 br label %loop.latch684 685loop.latch:686 %sr = phi i8 [ 0, %loop.header ], [ %l , %then ]687 %gep.dst = getelementptr i8, ptr %dst, i64 %iv688 store i8 %sr, ptr %gep.dst, align 4689 %inc = add i64 %iv, 1690 %exitcond.not = icmp eq i64 %inc, 4691 br i1 %exitcond.not, label %exit, label %loop.header692 693exit:694 ret void695}696 697; Variation of the above test with the poison value being used in all lanes.698define void @recipe_without_underlying_instr_lanes_used(i64 %n, ptr noalias %dst, ptr noalias %aux) {699; CHECK-LABEL: define void @recipe_without_underlying_instr_lanes_used(700; CHECK-SAME: i64 [[N:%.*]], ptr noalias [[DST:%.*]], ptr noalias [[AUX:%.*]]) {701; CHECK-NEXT: [[ENTRY:.*:]]702; CHECK-NEXT: br label %[[VECTOR_PH:.*]]703; CHECK: [[VECTOR_PH]]:704; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i64> poison, i64 [[N]], i64 0705; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> poison, <4 x i32> zeroinitializer706; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]707; CHECK: [[VECTOR_BODY]]:708; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i64> <i64 0, i64 1, i64 2, i64 3>, [[BROADCAST_SPLAT]]709; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0710; CHECK-NEXT: br i1 [[TMP2]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]711; CHECK: [[PRED_LOAD_IF]]:712; CHECK-NEXT: [[TMP16:%.*]] = add i64 0, poison713; CHECK-NEXT: [[TMP23:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP16]]714; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP23]], align 1715; CHECK-NEXT: [[TMP24:%.*]] = insertelement <4 x i8> poison, i8 [[TMP6]], i32 0716; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]717; CHECK: [[PRED_LOAD_CONTINUE]]:718; CHECK-NEXT: [[TMP25:%.*]] = phi <4 x i8> [ poison, %[[VECTOR_BODY]] ], [ [[TMP24]], %[[PRED_LOAD_IF]] ]719; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1720; CHECK-NEXT: br i1 [[TMP3]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2:.*]]721; CHECK: [[PRED_LOAD_IF1]]:722; CHECK-NEXT: [[TMP29:%.*]] = add i64 1, poison723; CHECK-NEXT: [[TMP30:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP29]]724; CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP30]], align 1725; CHECK-NEXT: [[TMP14:%.*]] = insertelement <4 x i8> [[TMP25]], i8 [[TMP13]], i32 1726; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]727; CHECK: [[PRED_LOAD_CONTINUE2]]:728; CHECK-NEXT: [[TMP15:%.*]] = phi <4 x i8> [ [[TMP25]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]729; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2730; CHECK-NEXT: br i1 [[TMP4]], label %[[PRED_LOAD_IF3:.*]], label %[[PRED_LOAD_CONTINUE4:.*]]731; CHECK: [[PRED_LOAD_IF3]]:732; CHECK-NEXT: [[TMP18:%.*]] = add i64 2, poison733; CHECK-NEXT: [[TMP19:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP18]]734; CHECK-NEXT: [[TMP20:%.*]] = load i8, ptr [[TMP19]], align 1735; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP15]], i8 [[TMP20]], i32 2736; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE4]]737; CHECK: [[PRED_LOAD_CONTINUE4]]:738; CHECK-NEXT: [[TMP22:%.*]] = phi <4 x i8> [ [[TMP15]], %[[PRED_LOAD_CONTINUE2]] ], [ [[TMP21]], %[[PRED_LOAD_IF3]] ]739; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3740; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF5:.*]], label %[[PRED_LOAD_CONTINUE6:.*]]741; CHECK: [[PRED_LOAD_IF5]]:742; CHECK-NEXT: [[TMP7:%.*]] = add i64 3, poison743; CHECK-NEXT: [[TMP8:%.*]] = getelementptr [5 x i8], ptr @c, i64 0, i64 [[TMP7]]744; CHECK-NEXT: [[TMP27:%.*]] = load i8, ptr [[TMP8]], align 1745; CHECK-NEXT: [[TMP28:%.*]] = insertelement <4 x i8> [[TMP22]], i8 [[TMP27]], i32 3746; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE6]]747; CHECK: [[PRED_LOAD_CONTINUE6]]:748; CHECK-NEXT: [[TMP26:%.*]] = phi <4 x i8> [ [[TMP22]], %[[PRED_LOAD_CONTINUE4]] ], [ [[TMP28]], %[[PRED_LOAD_IF5]] ]749; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> [[TMP26]], <4 x i8> zeroinitializer750; CHECK-NEXT: [[PREDPHI7:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> poison, <4 x i64> zeroinitializer751; CHECK-NEXT: [[TMP12:%.*]] = extractelement <4 x i64> [[PREDPHI7]], i32 3752; CHECK-NEXT: store i64 [[TMP12]], ptr [[AUX]], align 8753; CHECK-NEXT: store <4 x i8> [[PREDPHI]], ptr [[DST]], align 4754; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]755; CHECK: [[MIDDLE_BLOCK]]:756;757 758entry:759 br label %loop.header760 761loop.header:762 %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ]763 %cmp = icmp eq i64 %iv, %n764 br i1 %cmp, label %loop.latch, label %then765 766then:767 %rem = srem i64 3, 0768 %add3 = add i64 %rem, -3769 %add5 = add i64 %iv, %add3770 %gep = getelementptr [5 x i8], ptr @c, i64 0, i64 %add5771 %l = load i8, ptr %gep, align 1772 br label %loop.latch773 774loop.latch:775 %sr = phi i8 [ 0, %loop.header ], [ %l , %then ]776 %p = phi i64 [ 0, %loop.header ], [ %rem, %then ]777 store i64 %p, ptr %aux778 %gep.dst = getelementptr i8, ptr %dst, i64 %iv779 store i8 %sr, ptr %gep.dst, align 4780 %inc = add i64 %iv, 1781 %exitcond.not = icmp eq i64 %inc, 4782 br i1 %exitcond.not, label %exit, label %loop.header783 784exit:785 ret void786}787 788; %B.gep.0 and pointers based on it can preserve inbounds, as the inbounds789; versionused unconditionally in the store in the latch.790; FIXME: at the moment, inbounds is dropped from both the GEP feeding the vector load ans tore791define void @Bgep_inbounds_unconditionally_due_to_store(ptr noalias %B, ptr readonly %C) #0 {792; CHECK-LABEL: define void @Bgep_inbounds_unconditionally_due_to_store(793; CHECK-SAME: ptr noalias [[B:%.*]], ptr readonly [[C:%.*]]) #[[ATTR0]] {794; CHECK-NEXT: [[ENTRY:.*:]]795; CHECK-NEXT: br label %[[VECTOR_PH:.*]]796; CHECK: [[VECTOR_PH]]:797; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]798; CHECK: [[VECTOR_BODY]]:799; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]800; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[INDEX]]801; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4802; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <4 x i32> [[WIDE_LOAD]], splat (i32 20)803; CHECK-NEXT: [[TMP3:%.*]] = getelementptr float, ptr [[B]], i64 [[INDEX]]804; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, ptr [[TMP3]], align 4805; CHECK-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[WIDE_LOAD1]], splat (float 2.000000e+00)806; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP2]], <4 x float> splat (float 3.300000e+01), <4 x float> [[TMP5]]807; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[TMP3]], align 4808; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4809; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10000810; CHECK-NEXT: br i1 [[TMP7]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]811; CHECK: [[MIDDLE_BLOCK]]:812;813 814entry:815 br label %loop.body816 817loop.body:818 %iv1 = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]819 %C.gep = getelementptr inbounds i32, ptr %C, i64 %iv1820 %C.lv = load i32, ptr %C.gep, align 4821 %cmp = icmp eq i32 %C.lv, 20822 %B.gep.0 = getelementptr inbounds float, ptr %B, i64 %iv1823 br i1 %cmp, label %loop.latch, label %else824 825else:826 %B.lv = load float, ptr %B.gep.0, align 4827 %add = fadd float %B.lv, 2.0828 br label %loop.latch829 830loop.latch:831 %add.sink = phi float [ %add, %else ], [ 33.0, %loop.body ]832 store float %add.sink, ptr %B.gep.0, align 4833 %iv.next = add nuw nsw i64 %iv1, 1834 %exitcond.not = icmp eq i64 %iv.next, 10000835 br i1 %exitcond.not, label %exit, label %loop.body836 837exit:838 ret void839}840 841attributes #0 = { noinline nounwind uwtable "target-features"="+avx512bw,+avx512cd,+avx512dq,+avx512f,+avx512vl" }842attributes #1 = { "target-features"="+avx" }843 844!0 = !{}845