762 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 52; RUN: opt -p loop-vectorize -force-vector-width=2 -S %s | FileCheck %s3 4declare void @llvm.assume(i1)5 6; %a is known dereferenceable via assume for the whole loop.7define void @deref_assumption_in_preheader_non_constant_trip_count_access_i8(ptr noalias noundef %a, ptr noalias %b, ptr noalias %c, i64 %n) nofree nosync {8; CHECK-LABEL: define void @deref_assumption_in_preheader_non_constant_trip_count_access_i8(9; CHECK-SAME: ptr noalias noundef [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1:[0-9]+]] {10; CHECK-NEXT: [[ENTRY:.*]]:11; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 [[N]]) ]12; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 213; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]14; CHECK: [[VECTOR_PH]]:15; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 216; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]17; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]18; CHECK: [[VECTOR_BODY]]:19; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]20; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP0]]21; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[TMP0]]22; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i8>, ptr [[TMP2]], align 123; CHECK-NEXT: [[TMP4:%.*]] = icmp sge <2 x i8> [[WIDE_LOAD]], zeroinitializer24; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <2 x i8>, ptr [[TMP1]], align 125; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP4]], <2 x i8> [[WIDE_LOAD]], <2 x i8> [[WIDE_LOAD1]]26; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 [[TMP0]]27; CHECK-NEXT: store <2 x i8> [[PREDPHI]], ptr [[TMP6]], align 128; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[TMP0]], 229; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]30; CHECK-NEXT: br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]31; CHECK: [[MIDDLE_BLOCK]]:32; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]33; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]34; CHECK: [[SCALAR_PH]]:35; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]36; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]37; CHECK: [[LOOP_HEADER]]:38; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]39; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[IV]]40; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[IV]]41; CHECK-NEXT: [[L_B:%.*]] = load i8, ptr [[GEP_B]], align 142; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[L_B]], 043; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]44; CHECK: [[LOOP_THEN]]:45; CHECK-NEXT: [[L_A:%.*]] = load i8, ptr [[GEP_A]], align 146; CHECK-NEXT: br label %[[LOOP_LATCH]]47; CHECK: [[LOOP_LATCH]]:48; CHECK-NEXT: [[MERGE:%.*]] = phi i8 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]49; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 [[IV]]50; CHECK-NEXT: store i8 [[MERGE]], ptr [[GEP_C]], align 151; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 152; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]53; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP3:![0-9]+]]54; CHECK: [[EXIT]]:55; CHECK-NEXT: ret void56;57entry:58 call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 %n) ]59 br label %loop.header60 61loop.header:62 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]63 %gep.a = getelementptr inbounds i8, ptr %a, i64 %iv64 %gep.b = getelementptr inbounds i8, ptr %b, i64 %iv65 %l.b = load i8, ptr %gep.b, align 166 %c.1 = icmp sge i8 %l.b, 067 br i1 %c.1, label %loop.latch, label %loop.then68 69loop.then:70 %l.a = load i8, ptr %gep.a, align 171 br label %loop.latch72 73loop.latch:74 %merge = phi i8 [ %l.a, %loop.then ], [ %l.b, %loop.header ]75 %gep.c = getelementptr inbounds i8, ptr %c, i64 %iv76 store i8 %merge, ptr %gep.c, align 177 %iv.next = add nuw nsw i64 %iv, 178 %ec = icmp eq i64 %iv.next, %n79 br i1 %ec, label %exit, label %loop.header80 81exit:82 ret void83}84 85; %a is known dereferenceable via assume for the whole loop.86define void @deref_assumption_in_preheader_non_constant_trip_count_access_i32(ptr noalias noundef %a, ptr noalias %b, ptr noalias %c, i64 %n) nofree nosync {87; CHECK-LABEL: define void @deref_assumption_in_preheader_non_constant_trip_count_access_i32(88; CHECK-SAME: ptr noalias noundef [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {89; CHECK-NEXT: [[ENTRY:.*]]:90; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[N]], 491; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 [[MUL]]) ]92; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 293; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]94; CHECK: [[VECTOR_PH]]:95; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 296; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]97; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]98; CHECK: [[VECTOR_BODY]]:99; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]100; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]101; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]102; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 1103; CHECK-NEXT: [[TMP4:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer104; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <2 x i32>, ptr [[TMP1]], align 1105; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[WIDE_LOAD1]]106; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]107; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP6]], align 1108; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[TMP0]], 2109; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]110; CHECK-NEXT: br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]111; CHECK: [[MIDDLE_BLOCK]]:112; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]113; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]114; CHECK: [[SCALAR_PH]]:115; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]116; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]117; CHECK: [[LOOP_HEADER]]:118; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]119; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]120; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]121; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 1122; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0123; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]124; CHECK: [[LOOP_THEN]]:125; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1126; CHECK-NEXT: br label %[[LOOP_LATCH]]127; CHECK: [[LOOP_LATCH]]:128; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]129; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]130; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1131; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1132; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]133; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP5:![0-9]+]]134; CHECK: [[EXIT]]:135; CHECK-NEXT: ret void136;137entry:138 %mul = mul nsw nuw i64 %n, 4139 call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 %mul) ]140 br label %loop.header141 142loop.header:143 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]144 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv145 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv146 %l.b = load i32, ptr %gep.b, align 1147 %c.1 = icmp sge i32 %l.b, 0148 br i1 %c.1, label %loop.latch, label %loop.then149 150loop.then:151 %l.a = load i32, ptr %gep.a, align 1152 br label %loop.latch153 154loop.latch:155 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]156 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv157 store i32 %merge, ptr %gep.c, align 1158 %iv.next = add nuw nsw i64 %iv, 1159 %ec = icmp eq i64 %iv.next, %n160 br i1 %ec, label %exit, label %loop.header161 162exit:163 ret void164}165 166 167; %a is NOT known dereferenceable via assume for the whole loop.168define void @deref_assumption_in_preheader_too_small_non_constant_trip_count_access_i32(ptr noalias noundef %a, ptr noalias %b, ptr noalias %c, i64 %n) nofree nosync {169; CHECK-LABEL: define void @deref_assumption_in_preheader_too_small_non_constant_trip_count_access_i32(170; CHECK-SAME: ptr noalias noundef [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {171; CHECK-NEXT: [[ENTRY:.*]]:172; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 [[N]]) ]173; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 2174; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]175; CHECK: [[VECTOR_PH]]:176; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 2177; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]178; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]179; CHECK: [[VECTOR_BODY]]:180; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]181; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]182; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 1183; CHECK-NEXT: [[TMP15:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], zeroinitializer184; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP15]], i32 0185; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]186; CHECK: [[PRED_LOAD_IF]]:187; CHECK-NEXT: [[TMP19:%.*]] = add i64 [[TMP0]], 0188; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP19]]189; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 1190; CHECK-NEXT: [[TMP18:%.*]] = insertelement <2 x i32> poison, i32 [[TMP17]], i32 0191; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]192; CHECK: [[PRED_LOAD_CONTINUE]]:193; CHECK-NEXT: [[TMP9:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP18]], %[[PRED_LOAD_IF]] ]194; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP15]], i32 1195; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]196; CHECK: [[PRED_LOAD_IF1]]:197; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP0]], 1198; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]]199; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 1200; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> [[TMP9]], i32 [[TMP13]], i32 1201; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]202; CHECK: [[PRED_LOAD_CONTINUE2]]:203; CHECK-NEXT: [[TMP20:%.*]] = phi <2 x i32> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]204; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP15]], <2 x i32> [[TMP20]], <2 x i32> [[WIDE_LOAD]]205; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]206; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP6]], align 1207; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[TMP0]], 2208; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]209; CHECK-NEXT: br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]210; CHECK: [[MIDDLE_BLOCK]]:211; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]212; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]213; CHECK: [[SCALAR_PH]]:214; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]215; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]216; CHECK: [[LOOP_HEADER]]:217; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]218; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]219; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]220; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 1221; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0222; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]223; CHECK: [[LOOP_THEN]]:224; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1225; CHECK-NEXT: br label %[[LOOP_LATCH]]226; CHECK: [[LOOP_LATCH]]:227; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]228; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]229; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1230; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1231; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]232; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]]233; CHECK: [[EXIT]]:234; CHECK-NEXT: ret void235;236entry:237 call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 %n) ]238 br label %loop.header239 240loop.header:241 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]242 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv243 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv244 %l.b = load i32, ptr %gep.b, align 1245 %c.1 = icmp sge i32 %l.b, 0246 br i1 %c.1, label %loop.latch, label %loop.then247 248loop.then:249 %l.a = load i32, ptr %gep.a, align 1250 br label %loop.latch251 252loop.latch:253 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]254 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv255 store i32 %merge, ptr %gep.c, align 1256 %iv.next = add nuw nsw i64 %iv, 1257 %ec = icmp eq i64 %iv.next, %n258 br i1 %ec, label %exit, label %loop.header259 260exit:261 ret void262}263 264; %a is NOT known dereferenceable via assume for the whole loop.265define void @deref_assumption_in_preheader_too_small2_non_constant_trip_count_access_i32(ptr noalias noundef %a, ptr noalias %b, ptr noalias %c, i64 %n) nofree nosync {266; CHECK-LABEL: define void @deref_assumption_in_preheader_too_small2_non_constant_trip_count_access_i32(267; CHECK-SAME: ptr noalias noundef [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {268; CHECK-NEXT: [[ENTRY:.*]]:269; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 100) ]270; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 2271; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]272; CHECK: [[VECTOR_PH]]:273; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 2274; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]275; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]276; CHECK: [[VECTOR_BODY]]:277; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]278; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]279; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 1280; CHECK-NEXT: [[TMP15:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], zeroinitializer281; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP15]], i32 0282; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]283; CHECK: [[PRED_LOAD_IF]]:284; CHECK-NEXT: [[TMP19:%.*]] = add i64 [[TMP0]], 0285; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP19]]286; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 1287; CHECK-NEXT: [[TMP18:%.*]] = insertelement <2 x i32> poison, i32 [[TMP17]], i32 0288; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]289; CHECK: [[PRED_LOAD_CONTINUE]]:290; CHECK-NEXT: [[TMP9:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP18]], %[[PRED_LOAD_IF]] ]291; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP15]], i32 1292; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]293; CHECK: [[PRED_LOAD_IF1]]:294; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP0]], 1295; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]]296; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 1297; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> [[TMP9]], i32 [[TMP13]], i32 1298; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]299; CHECK: [[PRED_LOAD_CONTINUE2]]:300; CHECK-NEXT: [[TMP20:%.*]] = phi <2 x i32> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]301; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP15]], <2 x i32> [[TMP20]], <2 x i32> [[WIDE_LOAD]]302; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]303; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP6]], align 1304; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[TMP0]], 2305; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]306; CHECK-NEXT: br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]307; CHECK: [[MIDDLE_BLOCK]]:308; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]309; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]310; CHECK: [[SCALAR_PH]]:311; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]312; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]313; CHECK: [[LOOP_HEADER]]:314; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]315; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]316; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]317; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 1318; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0319; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]320; CHECK: [[LOOP_THEN]]:321; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1322; CHECK-NEXT: br label %[[LOOP_LATCH]]323; CHECK: [[LOOP_LATCH]]:324; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]325; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]326; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1327; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1328; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]329; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP9:![0-9]+]]330; CHECK: [[EXIT]]:331; CHECK-NEXT: ret void332;333entry:334 call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 100) ]335 br label %loop.header336 337loop.header:338 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]339 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv340 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv341 %l.b = load i32, ptr %gep.b, align 1342 %c.1 = icmp sge i32 %l.b, 0343 br i1 %c.1, label %loop.latch, label %loop.then344 345loop.then:346 %l.a = load i32, ptr %gep.a, align 1347 br label %loop.latch348 349loop.latch:350 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]351 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv352 store i32 %merge, ptr %gep.c, align 1353 %iv.next = add nuw nsw i64 %iv, 1354 %ec = icmp eq i64 %iv.next, %n355 br i1 %ec, label %exit, label %loop.header356 357exit:358 ret void359}360 361; %a is known dereferenceable via assume for the whole loop, alignment is known via function attribute.362define void @deref_assumption_in_preheader_non_constant_trip_count_access_i32_align_attribute(ptr noalias noundef align 4 %a, ptr noalias %b, ptr noalias %c, i64 %n) nofree nosync {363; CHECK-LABEL: define void @deref_assumption_in_preheader_non_constant_trip_count_access_i32_align_attribute(364; CHECK-SAME: ptr noalias noundef align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {365; CHECK-NEXT: [[ENTRY:.*]]:366; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[N]], 4367; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 [[MUL]]) ]368; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 2369; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]370; CHECK: [[VECTOR_PH]]:371; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 2372; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]373; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]374; CHECK: [[VECTOR_BODY]]:375; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]376; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[A]], i64 [[INDEX]]377; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]]378; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP1]], align 4379; CHECK-NEXT: [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer380; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <2 x i32>, ptr [[TMP0]], align 4381; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[WIDE_LOAD1]]382; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[INDEX]]383; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP5]], align 1384; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2385; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]386; CHECK-NEXT: br i1 [[TMP7]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]]387; CHECK: [[MIDDLE_BLOCK]]:388; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]389; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]390; CHECK: [[SCALAR_PH]]:391; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]392; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]393; CHECK: [[LOOP_HEADER]]:394; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]395; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]396; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]397; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4398; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0399; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]400; CHECK: [[LOOP_THEN]]:401; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4402; CHECK-NEXT: br label %[[LOOP_LATCH]]403; CHECK: [[LOOP_LATCH]]:404; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]405; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]406; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1407; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1408; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]409; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP11:![0-9]+]]410; CHECK: [[EXIT]]:411; CHECK-NEXT: ret void412;413entry:414 %mul = mul nsw nuw i64 %n, 4415 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 %mul) ]416 br label %loop.header417 418loop.header:419 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]420 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv421 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv422 %l.b = load i32, ptr %gep.b, align 4423 %c.1 = icmp sge i32 %l.b, 0424 br i1 %c.1, label %loop.latch, label %loop.then425 426loop.then:427 %l.a = load i32, ptr %gep.a, align 4428 br label %loop.latch429 430loop.latch:431 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]432 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv433 store i32 %merge, ptr %gep.c, align 1434 %iv.next = add nuw nsw i64 %iv, 1435 %ec = icmp eq i64 %iv.next, %n436 br i1 %ec, label %exit, label %loop.header437 438exit:439 ret void440}441 442; Alignment via argument attribute is too small (1 but needs 4).443define void @deref_assumption_in_preheader_non_constant_trip_count_access_i32_align_attribute_too_small(ptr noalias noundef align 1 %a, ptr noalias %b, ptr noalias %c, i64 %n) nofree nosync {444; CHECK-LABEL: define void @deref_assumption_in_preheader_non_constant_trip_count_access_i32_align_attribute_too_small(445; CHECK-SAME: ptr noalias noundef align 1 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {446; CHECK-NEXT: [[ENTRY:.*]]:447; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[N]], 4448; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 [[MUL]]) ]449; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 2450; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]451; CHECK: [[VECTOR_PH]]:452; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 2453; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]454; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]455; CHECK: [[VECTOR_BODY]]:456; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]457; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]]458; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP0]], align 4459; CHECK-NEXT: [[TMP3:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], zeroinitializer460; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i1> [[TMP3]], i32 0461; CHECK-NEXT: br i1 [[TMP4]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]462; CHECK: [[PRED_LOAD_IF]]:463; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDEX]], 0464; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP5]]465; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4466; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x i32> poison, i32 [[TMP7]], i32 0467; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]468; CHECK: [[PRED_LOAD_CONTINUE]]:469; CHECK-NEXT: [[TMP9:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP8]], %[[PRED_LOAD_IF]] ]470; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP3]], i32 1471; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]472; CHECK: [[PRED_LOAD_IF1]]:473; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[INDEX]], 1474; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]]475; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4476; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> [[TMP9]], i32 [[TMP13]], i32 1477; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]478; CHECK: [[PRED_LOAD_CONTINUE2]]:479; CHECK-NEXT: [[TMP15:%.*]] = phi <2 x i32> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]480; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP15]], <2 x i32> [[WIDE_LOAD]]481; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[INDEX]]482; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP16]], align 1483; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2484; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]485; CHECK-NEXT: br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]]486; CHECK: [[MIDDLE_BLOCK]]:487; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]488; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]489; CHECK: [[SCALAR_PH]]:490; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]491; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]492; CHECK: [[LOOP_HEADER]]:493; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]494; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]495; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]496; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4497; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0498; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]499; CHECK: [[LOOP_THEN]]:500; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4501; CHECK-NEXT: br label %[[LOOP_LATCH]]502; CHECK: [[LOOP_LATCH]]:503; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]504; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]505; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1506; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1507; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]508; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP13:![0-9]+]]509; CHECK: [[EXIT]]:510; CHECK-NEXT: ret void511;512entry:513 %mul = mul nsw nuw i64 %n, 4514 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 %mul) ]515 br label %loop.header516 517loop.header:518 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]519 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv520 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv521 %l.b = load i32, ptr %gep.b, align 4522 %c.1 = icmp sge i32 %l.b, 0523 br i1 %c.1, label %loop.latch, label %loop.then524 525loop.then:526 %l.a = load i32, ptr %gep.a, align 4527 br label %loop.latch528 529loop.latch:530 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]531 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv532 store i32 %merge, ptr %gep.c, align 1533 %iv.next = add nuw nsw i64 %iv, 1534 %ec = icmp eq i64 %iv.next, %n535 br i1 %ec, label %exit, label %loop.header536 537exit:538 ret void539}540 541; The start access is SCEV with non-constant offset because of variable `iv.start`542; for IV.543define void @deref_assumption_loop_access_start_variable(i8 %v, ptr noundef %P, i64 range(i64 0, 2000) %N, ptr noalias %b, ptr noalias %c, i64 range(i64 0, 2000) %iv.start) nofree nosync {544; CHECK-LABEL: define void @deref_assumption_loop_access_start_variable(545; CHECK-SAME: i8 [[V:%.*]], ptr noundef [[P:%.*]], i64 range(i64 0, 2000) [[N:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 range(i64 0, 2000) [[IV_START:%.*]]) #[[ATTR1]] {546; CHECK-NEXT: [[ENTRY:.*]]:547; CHECK-NEXT: [[A:%.*]] = getelementptr i8, ptr [[P]], i64 16548; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV_START]], [[N]]549; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])550; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[N]], 4551; CHECK-NEXT: [[ADD:%.*]] = add i64 [[MUL]], 16552; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 [[ADD]]) ]553; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[N]], [[IV_START]]554; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 2555; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]556; CHECK: [[VECTOR_PH]]:557; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 2558; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]]559; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[IV_START]], [[N_VEC]]560; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]561; CHECK: [[VECTOR_BODY]]:562; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]563; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 [[IV_START]], [[INDEX]]564; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[OFFSET_IDX]]565; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP6]], align 1566; CHECK-NEXT: [[TMP4:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], zeroinitializer567; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0568; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]569; CHECK: [[PRED_LOAD_IF]]:570; CHECK-NEXT: [[TMP16:%.*]] = add i64 [[OFFSET_IDX]], 0571; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP16]]572; CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP7]], align 1573; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x i32> poison, i32 [[TMP19]], i32 0574; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]575; CHECK: [[PRED_LOAD_CONTINUE]]:576; CHECK-NEXT: [[TMP10:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP9]], %[[PRED_LOAD_IF]] ]577; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1578; CHECK-NEXT: br i1 [[TMP11]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]579; CHECK: [[PRED_LOAD_IF1]]:580; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[OFFSET_IDX]], 1581; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP12]]582; CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 1583; CHECK-NEXT: [[TMP15:%.*]] = insertelement <2 x i32> [[TMP10]], i32 [[TMP14]], i32 1584; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]585; CHECK: [[PRED_LOAD_CONTINUE2]]:586; CHECK-NEXT: [[TMP20:%.*]] = phi <2 x i32> [ [[TMP10]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP15]], %[[PRED_LOAD_IF1]] ]587; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[TMP20]], <2 x i32> [[WIDE_LOAD]]588; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[OFFSET_IDX]]589; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 1590; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2591; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]592; CHECK-NEXT: br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]]593; CHECK: [[MIDDLE_BLOCK]]:594; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]]595; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]596; CHECK: [[SCALAR_PH]]:597; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP1]], %[[MIDDLE_BLOCK]] ], [ [[IV_START]], %[[ENTRY]] ]598; CHECK-NEXT: br label %[[LOOP:.*]]599; CHECK: [[LOOP]]:600; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]601; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]602; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]603; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 1604; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0605; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]606; CHECK: [[LOOP_THEN]]:607; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1608; CHECK-NEXT: br label %[[LOOP_LATCH]]609; CHECK: [[LOOP_LATCH]]:610; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP]] ]611; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]612; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1613; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1614; CHECK-NEXT: [[TERM_COND:%.*]] = icmp slt i64 [[IV_NEXT]], [[N]]615; CHECK-NEXT: br i1 [[TERM_COND]], label %[[LOOP]], label %[[EXIT]], !llvm.loop [[LOOP15:![0-9]+]]616; CHECK: [[EXIT]]:617; CHECK-NEXT: ret void618;619 620entry:621 %a = getelementptr i8, ptr %P, i64 16622 %cmp = icmp slt i64 %iv.start, %N623 call void @llvm.assume(i1 %cmp)624 %mul = mul i64 %N, 4625 %add = add i64 %mul, 16626 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %P, i64 %add) ]627 br label %loop628 629loop: ; preds = %mainloop, %loop.latch630 %iv = phi i64 [ %iv.next, %loop.latch ], [ %iv.start, %entry ]631 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv632 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv633 %l.b = load i32, ptr %gep.b, align 1634 %c.1 = icmp sge i32 %l.b, 0635 br i1 %c.1, label %loop.latch, label %loop.then636 637loop.then: ; preds = %loop638 %l.a = load i32, ptr %gep.a, align 1639 br label %loop.latch640 641loop.latch: ; preds = %loop.then, %loop642 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop ]643 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv644 store i32 %merge, ptr %gep.c, align 1645 %iv.next = add nuw nsw i64 %iv, 1646 %term.cond = icmp slt i64 %iv.next, %N647 br i1 %term.cond, label %loop, label %exit648 649exit:650 ret void651}652 653; Same as previous test, but `iv.start` is not known nonnegative.654define void @deref_assumption_loop_access_start_variable_unknown_range(i8 %v, ptr noundef %P, i64 range(i64 0, 2000) %N, ptr noalias %b, ptr noalias %c, i64 %iv.start) nofree nosync {655; CHECK-LABEL: define void @deref_assumption_loop_access_start_variable_unknown_range(656; CHECK-SAME: i8 [[V:%.*]], ptr noundef [[P:%.*]], i64 range(i64 0, 2000) [[N:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[IV_START:%.*]]) #[[ATTR1]] {657; CHECK-NEXT: [[ENTRY:.*]]:658; CHECK-NEXT: [[A:%.*]] = getelementptr i8, ptr [[P]], i64 16659; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV_START]], [[N]]660; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])661; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[N]], 4662; CHECK-NEXT: [[ADD:%.*]] = add i64 [[MUL]], 16663; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 [[ADD]]) ]664; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[N]], [[IV_START]]665; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 2666; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]667; CHECK: [[VECTOR_PH]]:668; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], 2669; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]]670; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[IV_START]], [[N_VEC]]671; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]672; CHECK: [[VECTOR_BODY]]:673; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]674; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 [[IV_START]], [[INDEX]]675; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[OFFSET_IDX]]676; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 1677; CHECK-NEXT: [[TMP4:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], zeroinitializer678; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0679; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]680; CHECK: [[PRED_LOAD_IF]]:681; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[OFFSET_IDX]], 0682; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP6]]683; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 1684; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x i32> poison, i32 [[TMP8]], i32 0685; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]]686; CHECK: [[PRED_LOAD_CONTINUE]]:687; CHECK-NEXT: [[TMP10:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP9]], %[[PRED_LOAD_IF]] ]688; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1689; CHECK-NEXT: br i1 [[TMP11]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]690; CHECK: [[PRED_LOAD_IF1]]:691; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[OFFSET_IDX]], 1692; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP12]]693; CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 1694; CHECK-NEXT: [[TMP15:%.*]] = insertelement <2 x i32> [[TMP10]], i32 [[TMP14]], i32 1695; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]]696; CHECK: [[PRED_LOAD_CONTINUE2]]:697; CHECK-NEXT: [[TMP16:%.*]] = phi <2 x i32> [ [[TMP10]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP15]], %[[PRED_LOAD_IF1]] ]698; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[TMP16]], <2 x i32> [[WIDE_LOAD]]699; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[OFFSET_IDX]]700; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 1701; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2702; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]703; CHECK-NEXT: br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]]704; CHECK: [[MIDDLE_BLOCK]]:705; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]]706; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]707; CHECK: [[SCALAR_PH]]:708; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP1]], %[[MIDDLE_BLOCK]] ], [ [[IV_START]], %[[ENTRY]] ]709; CHECK-NEXT: br label %[[LOOP:.*]]710; CHECK: [[LOOP]]:711; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]712; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]]713; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]714; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 1715; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0716; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]717; CHECK: [[LOOP_THEN]]:718; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1719; CHECK-NEXT: br label %[[LOOP_LATCH]]720; CHECK: [[LOOP_LATCH]]:721; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP]] ]722; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]723; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 1724; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1725; CHECK-NEXT: [[TERM_COND:%.*]] = icmp slt i64 [[IV_NEXT]], [[N]]726; CHECK-NEXT: br i1 [[TERM_COND]], label %[[LOOP]], label %[[EXIT]], !llvm.loop [[LOOP17:![0-9]+]]727; CHECK: [[EXIT]]:728; CHECK-NEXT: ret void729;730entry:731 %a = getelementptr i8, ptr %P, i64 16732 %cmp = icmp slt i64 %iv.start, %N733 call void @llvm.assume(i1 %cmp)734 %mul = mul i64 %N, 4735 %add = add i64 %mul, 16736 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %P, i64 %add) ]737 br label %loop738 739loop: ; preds = %mainloop, %loop.latch740 %iv = phi i64 [ %iv.next, %loop.latch ], [ %iv.start, %entry ]741 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv742 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv743 %l.b = load i32, ptr %gep.b, align 1744 %c.1 = icmp sge i32 %l.b, 0745 br i1 %c.1, label %loop.latch, label %loop.then746 747loop.then: ; preds = %loop748 %l.a = load i32, ptr %gep.a, align 1749 br label %loop.latch750 751loop.latch: ; preds = %loop.then, %loop752 %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop ]753 %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv754 store i32 %merge, ptr %gep.c, align 1755 %iv.next = add nuw nsw i64 %iv, 1756 %term.cond = icmp slt i64 %iv.next, %N757 br i1 %term.cond, label %loop, label %exit758 759exit:760 ret void761}762