brintos

brintos / llvm-project-archived public Read only

0
0
Text · 42.2 KiB · 8417e22 Raw
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